일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- urlconnection
- 안드로이드 http
- Bottom sheet
- 앱개발
- Dialog
- Exposed Drop-Down Menu
- 안드로이드 api
- Callback
- 비동기
- 플레이 콘솔 프로덕션
- 앱 출시
- 안드로이드스튜디오
- 공유 기능
- android api
- Retrofit
- android studio
- 안드로이드 스튜디오
- Kotlin
- 플레이스토어 앱 게시 문제
- Today
- Total
Strong 감자의 공부
Ch_ 06 내장자료형 알아보기 본문
목차
1. 내장 자료형 알아보기
- 1.2 문자와 문자열 자료형
- 1.3 Any, Unit, Nothing 클래스
- 1.4 배열
2. 자료형 처리 알아보기
- 2.1 널러블 여부
- 2.2 타입 변환
- 2.3 구조 분해
1. 내장 자료형 알아보기
🔶1.2 문자와 문자열 자료형
문자열은 기본으로 변경할 수 없는 객체이다. 제공되는 메서드는 기존 문자열을 변경해서 새로운 문자열을 만들어준다. 문자열을 변경할려면 StringBuilder클래스를 사용해야한다.
⚫문자열의 원소는 문자 클래스의 객체이다.
fun main(){
println("강" in "강아지") // 문자열 내에 특정 문자가 포함되어 있는지 in 연산자로 확인
val sb = StringBuilder("강아지")
println("강아지".javaClass.kotlin)
println(sb.javaClass.kotlin)
println('강' in sb)
println("강아지"== sb.toString()) // 문자열과 연산하기위해선 StringBuilder는 다른 클래스라 문자열로 변환필요
}
// 결과값
true
class kotlin.String
class java.lang.StringBuilder
true
true
⚫ 문자열 메서드로 내부 조회
fun main(){
val myString = "문자열 인덱스 조회"
val item = myString[2]
println(myString.first()) // 문자열의 첫번째 문자
println(myString.last()) // 문자열의 끝문자
println(myString[0]) // 인덱스 0번
println(myString[myString.length-1]) // 인덱스 마지막 문자
println(myString.lastIndex) // 마지막 인덱스 값 반환
println(myString.get(2)) // 인덱스 2번 문자
println(myString.getOrElse(myString.length,{'2'})) // 인덱스 범위를 벗어날 경우 2를 반환
println(myString.getOrNull(myString.length)) // 인덱스 범위를 벗어날 경우 null 반환
}
// 결과값
문
회
문
회
9
열
2
null
⚫ 빈 문자열 처리
fun main(){
val s1 = "\t"
if(s1.isEmpty()) println("문자열 내에 문자가 없음") // \t 이스케이프 문자를 문자로 봄
else println("이스케이프가 문자열에 있음")
if(s1.isBlank()) println("빈 문자열") // \t 이스케이프 문자는 문자로 안봄
else println("이스케이프가 문자열에 있음")
val s2 = " 1234\t"
println("문자 개수는 ${s2.length}") // 공백, 이스케이프문자도 문자로 취급
val s3 = s2.trimEnd()
println("문자 개수는 ${s3.length}")
val s4=s2.trimStart()
println("문자 개수는 ${s4.length}")
val s5=s2.trim()
println("문자 개수는 ${s5.length}")
}
// 결과값
이스케이프가 문자열에 있음
빈 문자열
문자 개수는 6
문자 개수는 5
문자 개수는 5
문자 개수는 4
⚫ 문자열 비교와 대소문자 등의 메서드
fun main() {
val s1 = "Eagle"
val s2 = "eagle"
if (s1 == s2) println("대소문자 구분x") // == 대소문자 구분함
else println("대소문자 구분함")
val res1 = s1.compareTo(s2) // 대소문자 비교하지 않는게 디폴트로 false, 즉 대소문자 구분함
println(res1)
if (res1 == 0) println("대소문자 구분x")
else println("대소문자 구분함")
val res2 = s1.compareTo(s2, true) // 대소문자 비교함
println(res2)
if (res2 == 0) println("대소문자 구분x")
else println("대소문자 구분함")
val s3 = "gamja"
println(s3.replaceFirstChar({ it.uppercase() })) // 첫번째 문자를 대문자로 변경
println("DolJavBan".replaceFirstChar({ it.lowercase() })) // 문자열의 첫번째 문자인 대문자를 소문자로 변경
println(s3.uppercase()) // 다 대문자로 변경
println(s3.lowercase()) // 다 소문자로 변경
val s4 = "튜플" to "만들기"
println(s4)
}
// 결과값
대소문자 구분함
-32
대소문자 구분함
0
대소문자 구분x
Gamja
dolJavBan
GAMJA
gamja
(튜플, 만들기)
⚫ 문자 필터링 처리
문자열도 여러 문자들을 가지므로 filter 등 내부 순환을 제공한다.
메서드 filter는 내부순환을 돌면서 람다표현식이 실행한 결과가 참인 경우만 추출하고 for를 대체할 수 있다.
아래 확장함수는 문자 중 모음만 추출한다.
fun Char.isEnglishVowel(): Boolean =
this.lowercase() == 'a'.toString()
|| this.lowercase() == 'e'.toString()
|| this.lowercase() == 'i'.toString()
|| this.lowercase() == 'o'.toString()
|| this.lowercase() == 'u'.toString()
fun main() {
val s = "Abcd EfgHijk"
val res1 = s.filter { e -> e.isEnglishVowel() } // 문자열 필터해서 맞는 문자만 추출
println("result1 = ${res1}") //result = AEi
var res2 = ""
for (i in s) { // i의 자료형은 Char
if (i.isEnglishVowel()) {
res2 += i.toString()
}
}
println("result2 = ${res2}") // result2 = AEi
}
⚫ 리스트 등의 문자열 처리
fun main() {
val words = listOf("gamja", "doljaban", "mom", "boy", "atom", "abo")
// filter는 반환값이 List<string>
val res1 = words.filter { e -> e.startsWith("bo") } // 리스트에서 bo로 시작하는 원소들을 리스트에서 가져온다.
println("리스트에서 b로 시작하는 문자= $res1")
val res2 = words.filter { e -> e.endsWith("a") } // 리스트에서 a로 끝나는 원소들을 리스트에서 가져온다.
println("리스트에서 a로 끝나는 문자= $res2")
val ml = mutableListOf("abc", "fgg", "vvv", "rtaby", "affb", "yab", "abf")
// find는 반환값이 string
val res3 = ml.find { it.startsWith("ab") } // 리스트의 앞에서부터 순환하는데 문자열 앞이 ab로 시작하면 반환
val res4 = ml.findLast { it.startsWith("ab") } // 리스트의 뒤에서부터 순환하는데 문자열 앞이 ab로 시작하면 반환
println("res3 : ${res3}")
println("res4 : ${res4}")
val res5 = ml.find { it.endsWith("ab") } // 리스트의 앞에서부터 순환하는데 문자열 뒤가 ab로 시작하면 반환
val res6 = ml.findLast { it.endsWith("ab") } // 리스트의 뒤에서부터 순환하는데 문자열 뒤가 ab로 시작하면 반환
println("res5 : ${res5}")
println("res6 : ${res6}")
}
// 결과값
리스트에서 b로 시작하는 문자= [boy]
리스트에서 a로 끝나는 문자= [gamja]
res3 : abc
res4 : abf
res5 : yab
res6 : yab
⚫ 문자열 분해와 결합 등 메서드
fun main() {
val s1 = "Today is a sunny day."
val w1 = s1.replace("sunny", "rainy") // 1인수를 2번째 인수로 변경
println(w1)
val s2 = "Today is a sunny day."
println(s2.contains("Today")) // 인수 포함 여부
val word = "독수리, 매, 올빼미, 까치"
val w2 = word.split(",")
println(w2) // 문자열을 , 로 구분 후 list로 반환
val joins = w2.joinToString("/") // 문자열 리스트들을 /로 문자열로
println(joins)
// 문자열 자르기
val w3 = "감자는 공부중"
println(w3.substring(2, 3)) // 문자열 인덱스 2<= <3 자름
println(w3.slice(1..2)) // 문자열 인덱스 1~2포함 자름
}
// 결과값
Today is a rainy day.
true
[독수리, 매, 올빼미, 까치]
독수리/ 매/ 올빼미/ 까치
는
자는
⚫변경가능한 문자열 StringBuilder
fun main() {
var str = StringBuilder()
println("1. 문자열 : $str")
println(" 길이= ${str.length} 용량=${str.capacity()}") // 현재 사용가능한 용량 확인
// append는 마지막인덱스에 추가
str.append(5) // 마지막 인덱스에 5추가
str.append("강아지")
str.append('가')
str.append(true)
println("2. 문자열 : $str")
println(" 길이= ${str.length} 용량=${str.capacity()}") // 현재 사용가능한 용량 확인
// insert는 특정 인덱스에 추가
str.insert(1, "000")
println("3. 문자열 : $str")
println(" 길이= ${str.length} 용량=${str.capacity()}") // 현재 사용가능한 용량 확인
// 삭제
str.deleteCharAt(0) // 0번째 인덱스갑 삭제
println("4. 문자열 : $str")
str.delete(0, 2) // 인덱스 0~1번째 원소 삭제
println("5. 문자열 : $str")
str.clear()
println("6. 문자열 : $str")
str.append("안녕")
println("7. 문자열 : $str")
str.setCharAt(0, '하') // 인덱스 0번 문자 변경
println("8. 문자열 : $str")
str.append("안녕하세요 감자구리구리구리구리")
println("9. 문자열 : $str")
println(" 길이= ${str.length} 용량=${str.capacity()}") // 현재 사용가능한 용량 확인, 늘어남
}
// 결과값
1. 문자열 :
길이= 0 용량=16
2. 문자열 : 5강아지가true
길이= 9 용량=16
3. 문자열 : 5000강아지가true
길이= 12 용량=16
4. 문자열 : 000강아지가true
5. 문자열 : 0강아지가true
6. 문자열 :
7. 문자열 : 안녕
8. 문자열 : 하녕
9. 문자열 : 하녕안녕하세요 감자구리구리구리구리
길이= 18 용량=34
🔶1.3 Any, Unit, Nothing 클래스
⚫ Any 클래스
어떤 클래스를 정의하든 Any 클래스는 자동으로 상속한다. 그래서 이 클래스에 확장함수를 지정하면 공통 메서드로 사용이 가능하다.
Any 클래스에서 제공하는 toString, hashCode 메서드는 하위 클래스에서 재정의해 사용할 수 있다. 보통 최상위 클래스에 정의된 메서드는 공통 메서드이다.
⚫ Unit 클래스
보통 반환값이 없다면 Unit 객체를 반환한다. println()함수도 출력 이후에 Unit클래스의 객체를 반환한다. 그래서 반환자료형에 Nothing을 쓰면 에러가 난다. Unit은 아무것도 하지 않지만, 항상 값을 반환한다.
⚫ Nothing 클래스
함수를 반환 때 아무것도 없다는 것을 표시하는 클래스이다. 보통 예외 등을 처리할 때 이 클래스의 객체가 발생한 것으로 여긴다. 이 클래스 또한 Any 클래스를 상속해서 구현한다.
🔶1.4 배열
fun main(){
val arInt = arrayOf(1,2,3,4)
println(arInt)
println(arInt.contentToString()) // 배열 자체 출력
println(arInt.size) // count랑 같다.
println(arInt.maxOrNull())
val arString = arrayOf("감자", "돌자반")
println(arString.maxOrNull())
}
// 결과값
[Ljava.lang.Integer;@3b9a45b3
[1, 2, 3, 4]
4
4
돌자반
⚫ 다양한 배열의 원소 출력법
indices라는 IntRange 타입의 값을 반환하는데 최소인덱스..최대인덱스이다.
fun main() {
val arInt = arrayOf(1, 2, 3, 4)
val x = arInt.indices.iterator()
while (x.hasNext()) {
println("next이용 " + x.next())
println(arInt.get(x.next()))
}
arInt.forEach { println("forEach" + it) }
arInt.forEachIndexed { i, e ->
println("$i = $e")
}
}
// 결과값
next이용 0
2
next이용 2
4
forEach1
forEach2
forEach3
forEach4
0 = 1
1 = 2
2 = 3
3 = 4
2. 자료형 처리 알아보기
🔶2.1 널러블 여부
⚫널러블 자료형 처리 규칙
- 널러블 자료형은 항상 널이 불가능한 자료형보다 상위 자료형이다. 그래서 널이 불가능한 자료형의 변수를 널러블 자료형의 변수에 할당할 수 있다. 반대로의 할당은 불가능하다.
- 널에 대한 체크는 컴파일 타임에 확정하지만, 실제 실행할 때는 처리하지 않는다. 그래서 널에 대한 처리는 전부 컴파일 처리할 때 예외를 발생시킨다.
- ?. : 널값이 들어오면 널로 처리하고 널값이 아니면 뒤에 오는 속성이나 메서드를 실행한다.
- ?: : 널값이면 다음에 들어오는 값으로 반환한다.
- !! : 널 값이 안들어온다고 확신할 경우만 사용한다. 널 값이 들어오면 예외를 발생시킨다.
⚫널 처리 메서드
fun main() {
val nullableList: List<Int?> = listOf(1,2,null,4)
println(nullableList.filterNotNull()) // 리스트내에서 널 제거
val s1= " \t\n"
println(s1.isNullOrEmpty()==false) // 비어있지 않은 걸로 봄
println(s1.isNullOrBlank()==false) // 비어있는 걸로 봄
}
// 결과값
[1, 2, 4]
true
false
🔶2.2 타입변환
⚫ 타입 체크 및 변환 연산자
is / !is : 상속관계에 해당하는 타입일 때만 is , !is로 점검할 수 있다.
as/ as? : 타입을 변환할 때도 상속관계 내에서 가능하고 불가능할 경우는 as?로 처리하면 null이 반환된다.
스마트 캐스팅의 경우 lateinit 이나 get() = " " 와 같이 명확한 초깃값이 아닐경우 되지않는다. 반대로 by lazy{} 지연초기화나 get() = 190 와 같이 명확한 값이 들어오는 경우는 문제가 없다.
⚫명시적인 자료형 변환
fun main() {
var x: String = "100"
var y: String? = "3000"
x = y as String // 널러블 문자열을 as를 사용해 일반 문자열로 변경해서 대입가능
println(x) // 3000
var e: String = "100"
var f: String? = null
val g = f as? String ?: 0 // 문자열에 null이 들어올 경우 as? 사용, ?:로 널대신 초기값반환
println(g) // 0
}
// 결과값
🔶2.3 구조분해 알아보기
⚫ 튜플 구조분해
fun main() {
val a = 100
val b = 200
val c = 300
val st = Triple(a, b, c)
val (a_, b_, c_) = st // 구조분해, 3개의 원소가 자동으로 변수에 할당
println("$a_, $b_, $c_")
// 투플내의 구조분해하는 속성확인, 퓨플 내 원소 조회
val e = st.first
val f = st.second
val g = st.third
println("$e, $f, $g")
// 실제 구조분해를 해서 변수에 할당하면 componentN메서드가 실행됨.
val e1 = st.component1()
val e2 = st.component2()
val e3 = st.component3()
println("$e1, $e2, $e3")
}
// 결과값
100, 200, 300
100, 200, 300
100, 200, 300
⚫ 배열의 구조분해
fun main() {
val arr = arrayOf("a", "b", "c")
println(arr.component1()) // a
println(arr.component2()) // b
println(arr.component3()) // c
// 변수를 정의해 구조분해
val (a1, a2, a3) = arr
println("$a1, $a2, $a3") // a, b, c
// 구조분해 시 미사용 변수를_로 지정
val (_, _, cc) = arr
println("$cc") // c
// 변수 개수가 부족하면 그 위치까지만 구조분해됨.
val (_, bb) = arr
println("$bb") // b
}
// 결과값
⚫ 데이터 클래스의 구조분해
import javax.xml.crypto.Data
data class DataClass(val name: String, val age: Int)
fun main() {
val dc = DataClass("감자", 25)
val (name, age) = dc // 변수할당 구조분해
println("$name, $age")
val n1 = dc.component1() // 메서드 사용 구조분해
val n2 = dc.component2()
println("name : $n1, age : $n2")
}
// 결과값
감자, 25
name : 감자, age : 25
⚫ 여러 인터페이스를 상속해 구현한 경우, 자료형으로 특정 인터페이스를 지정하면 클래스에 있는 모든 메서드를 호출하지 못하고 자료형에 지정된 인터페이스만 처리가 가능하다.
책에선 자료형으로 Abstract이 가능하던데 인텔리제이에선 안된다.
interface c {
fun add(x: Int, y: Int): Int
}
abstract class Ab {
abstract fun addA(x: Int, y: Int): Int
}
class Add : c, Ab() {
override fun add(x: Int, y: Int): Int = x + y
override fun addA(x: Int, y: Int): Int = x + y
}
fun main() {
val ai: c = Add()
println(ai.add(100, 200))
//println(ai.addA(100,200))은 인터페이스 범위가 아니라 호출 x
val abb: Ab = Add()
println(abb.addA(100, 200))
//println(abb.add(100,200))은 추상클래스 범위가 아니라 호출 x
}
// 결과값
300
300
'CS > 문법_Kotlin' 카테고리의 다른 글
Ch_10 함수 추가 사항 알아보기 (0) | 2023.09.13 |
---|---|
Ch_07 클래스 관계 등 추가 사항 알아보기 (0) | 2023.08.25 |
Ch_05 클래스 알아보기 (0) | 2023.08.11 |
Ch_04 함수 알아보기 (0) | 2023.08.04 |
Ch03_문장 제어 처리 알아보기 (0) | 2023.07.26 |