코틀린의 장점
언어의 생산성, 간결성
- 코틀린은 자바에 비해 간결하고 직관적이어서 가독성이 좋다.
- 생성자, getter, setter 등 자바의 여러 준비 코드들을 묵시적으로 제공하기에 깔끔하다.
- 다양한 표준 라이브러리를 제공해 반복되는 코드를 줄일 수 있다.
타입 추론
- var / val 키워드를 이용해 타입 추론이 가능하다.
- var: 초기화 후 값 변경이 가능한 변수
- val: 초기에 값을 할당하면 나중에는 변경할 수 없는 변수 (상수)
- s라는 변수가 String임을 명시하지 않았으나 할당된 값에 따라 타입 추론으로 타입을 정한다.
- s에 할당된 값으로 String 변수로 인식되고, String의 메소드를 사용할 수 있다.
fun main() {
val s = "hello ~"
println(s.substring(0, 5)) // hello
}
getter / setter 자동 생성
- 자바와 같이 Lombok의 도움을 받거나 개발자가 getter / setter를 작성하지 않는다.
- 코틀린은 객체 프로퍼티에 대하여 getter와 setter를 자동으로 생성한다.
- var: getter / setter 생성
- val: getter 생성0
- 아래 코드를 예제로 들어 User라는 클래스에는 상수인 id와 변수인 name이 존재한다.
- id는 상수이므로 getter만 자동으로 생성되고, 값 변경을 시도하면 컴파일 오류가 발생한다. (아래 사진처럼 빨간 줄이 뜨는 걸 확인할 수 있다.)
- name은 변수이므로 getter와 setter가 자동으로 생성된다.
- setter의 경우 >> user.setName("sy") << 와 같은 형태로 코드가 변환된다.
class User(
val id: String,
var name: String
)
fun main(){
val user = User("1", "abbiddo")
println(user.id) // 1
println(user.name) // abbiddo
// user.id = "2" val update error
user.name = "sy"
println(user.name) // sy
}
null 안전성
- 런타임 오류가 아닌 컴파일 시점 검사로 NullPointerException 에러를 방지한다.
- null 안정성 검사를 위해 if 문이나 try-catch문을 사용할 필요가 없다.
- 코틀린은 자바와 반대로 모든 객체 변수를 not-null로 정의한다.
- 객체 생성 시 뒤에 ?를 붙여 null-able 변수를 생성할 수 있다.
- not-null 변수에 null값을 넣으면 컴파일 시점에 에러를 발생한다.
- 아래 예제에서 name을 nullable 변수로 만들고, null일 수도 있는 값에 메소드를 호출하므로 컴파일에 실패한다.
- 특정 값이 null 일 경우 오류 방지를 위해 값을 넣어줄 수 있다.
class User(
val id: String,
var name: String,
var income: Int?
)
fun main(){
val user = User("1", "abbiddo", null)
val income: Int = user.income ?: 0
if (income == 0) {
println("나 돈 없어") // 출력
}
}
상호 운용성
- Java와 100% 호환된다.
- java 클래스를 kotlin에서, kotlin 클래스를 java 클래스에서 사용할 수 있다.
- java 클래스와 kotlin 클래스 모두 java bytecode로 변환된다.
확장된 문법
when
- 자바의 switch 문에 대응하는 문법이다.
- 별도의 break가 필요하지 않고, 변수 선언과 함께 바로 사용할 수 있다.
- 아래 코드의 첫 번째 예제는 조건에 만족하면 해당 코드를 실행하는 switch문의 가장 기본적인 형태와 유사하다.
- 두 번째 예제는 값을 반환해 선언한 변수에 값을 할당하는 예제다.
- 세 번째 예제는 Smart Cast의 예로 타입에 맞춰 정해진 코드를 실행한다.
- Any 타입은 null이 될 수 없는 타입의 조상 타입이다.
import kotlin.random.Random
class User(
val id: String,
var name: String
)
fun getRandomObject(): Any{
val randomValue = Random.nextInt(3)
return when (randomValue) {
0 -> "Hello, World!"
1 -> Random.nextInt(100)
2 -> User("1", "abbiddo")
else -> "Unknown Value"
}
}
fun main(){
// ------------ 1 ------------
val year = 2023
when {
year >= 2020 -> println("Covid era") // 출력
year >= 2000 -> println("Millennium")
year >= 1990 -> println("Apocalypse")
else -> println("Old days")
}
// ------------ 2 ------------
val score: Int = Random.nextInt(100)
val grade = when {
score >= 100 -> "Perfect"
score >= 90 -> "A+"
score >= 80 -> "A"
score >= 70 -> "B+"
score >= 60 -> "B"
score >= 50 -> "C+"
score >= 30 -> "C"
else -> "F"
}
println("$score: $grade") // 94: A+
// ------------ 3 ------------
when (val something: Any = getRandomObject()) {
is String -> println("this is string. So I can call uppercase() : ${something.uppercase()}")
is Int -> println("this is an integer. So I can add value : ${something + 5}")
is User -> println("this is an user! Nmae : ${something.name}")
}
}
Dstructive Declaration
- 파이썬의 튜플 처럼 각 프로퍼티의 순서에 맞춰 좌변에 변수들을 준비하면 각 위치에 대응하는 값들이 대입된다.
- Pair나 Triple 같은 자료구조를 활용하면 생산성을 높일 수 있다.
data class User(
val id: String,
var name: String
)
fun main(){
val user = User("1", "abbiddo")
val (id, name) = user
println(id) // 1
println(name) // abbiddo
}
궁금증
nullable인 변수에 null을 할당하고 메소드를 이용한다면 NPE가 발생할까?
=> 이 또한 컴파일 시점에 확인을 하고 NPE를 방지한다.
'Programming > Kotlin' 카테고리의 다른 글
[Kotlin] 코틀린 기본 문법: 범위 지정 메소드와 레이블 (0) | 2024.01.09 |
---|---|
[Kotlin] 코틀린 기본 문법: null safety, 널 안정성 (0) | 2024.01.08 |
[Kotlin] 코틀린 기본 문법: 포함 연산자와 동등성 (1) | 2024.01.08 |
[Kotlin] 코틀린 기본 문법: 변수와 입출력 (0) | 2024.01.08 |
[Kotlin] Data Class (0) | 2023.12.29 |