Kotlin은 Java와 달리 Null 처리에 높은 안정성을 가진다는 특징이 있다.
null 예외가 발생하면 앱이 다운되고, 이는 프로그램의 가용성을 저하시키는 치명적인 오류라고 할 수 있다.
코틀린에서는 자료형에 null 여부를 명시함으로서 안정성을 높일 수 있다. null 처리 안정성을 높이기 위해 "?", "!!", "?.", "?:" 와 같은 키워드를 사용한다.
1. "?" 키워드
Java에서는 NPE(Null Pointer Exception)를 런타임에서만(=실행을 해야만) 잡을 수 있는 반면, Kotlin에서는 이를 컴파일 시점에서도 잡기위해 "?" 키워드를 사용한다. ? 키워드를 사용하면 해당 변수가 Nullable 타입으로 사용된다.
fun nullCheck() {
var name: String = "tistory" //NonNull 타입
var nullName: String = null //Error 발생
var nullName2: String? = null //Nullable 타입이므로 Error 발생X
}
2. "!!" 키워드
"!!" 키워드는 Nullable 타입으로 지정되어 있지만 Null이 아님을 보증해줄 때 사용하는 키워드이다. (정말 확실한 경우가 아닌이상 사용을 지양)
fun ignoreNulls(str: String?) { //Nullable타입의 str
val mNotNull: String = str!! //str이 절대 null이 아니라는 의미
val upper = mNotNull.toUpperCase() //mNotNull? 로 하지않아도 Error 발생X
}
3. "?." 키워드 (safe-calls, 안전 호출 연산자)
Null인지 확인하고 Null이 아닐때만 참조하는 메소드를 실행하도록 하기위해 "?." 키워드를 사용한다.
fun main() {
var address: String? = null
println("주소의 길이는: ${address?.length} 입니다.")
// adress가 null인 경우 : “주소의 길이는 null 입니다” 출력
// adress가 null이 아닌 경우 : “주소의 길이는 5(임의) 입니다” 출력
}
4. "?:" 키워드 (엘비스 연산자)
?. 키워드로 안전하게 실행했지만 null 대신 default 값을 출력하고 싶을 때 사용하는 키워드가 바로 "?:" 키워드이다.
fun main() {
var address: String? = null
println("주소의 길이는: ${address?.length ?: "빈값"} 입니다.")
// adress가 null인 경우 : “주소의 길이는 빈값 입니다” 출력
// adress가 null이 아닌 경우 : “주소의 길이는 5(임의) 입니다” 출력
}
5. let 함수
추가로 한가지 더 다뤄보자면, 자신의 Receiver 객체를 람다식 내부로 옮겨서 실행하는 let 함수가 있다.
fun letSample() {
val email: String? = "aaa@gmail.com"
email?.let { //email이 null이 아닐때만 실행
println("my email is ${email}")
}
//email이 null이라면 아무것도 출력되지 않음
}
Null Safety에 대해 다뤄보았다면, 앞에 다룬 Nullable 타입으로 선언하고 이후 값을 대입하는 방법 말고 프로퍼티 초기화를 미루는 방법에 대해서도 알아보자.
이는 늦은 초기화, 혹은 지연 초기화라고 불리우는 방법이다. 초기의 값을 정의하기 난처한 상황일 때 나중에 값을 대입하기 위한 문법이라고 할 수 있다.
1. "lateinit" 키워드
"lateinit" 키워드는 변수의 지연초기화를 할 때 사용하는 키워드로, 이후에 초기값을 할당할 것임으로 명시적으로 선언한다.
lateinit 은 var 로 선언된 변수에만 사용이 가능하며 Int, Long, Short, Double, Float, Boolean, Byte 타입(Primitive Type)에는 사용이 불가하다.
var nullableNumber: Int? = null //사용할 때마다 ?나 !!를 사용하여 null 제거 필요
lateinit var lateinitName: String //지연초기화
lateinitName = "tistory" //초기화
if(this::name.isInitialized) { //값이 초기화되었는지 확인 (true/false 반환)
println("이름은 ${lateinitName} 입니다.")
}
2. "lazy" 키워드
"lazy" 키워드는 상수의 지연초기화를 할 때 사용하는 키워드로, 변수 선언문 뒤에 by lazy {...} 형식으로 선언되며 실제 사용되는 시점에 값을 대입하여 초기화가 수행된다. 안드로이드의 경우 View를 나중에 할당하는 경우에도 by lazy 키워드를 활용한다.
val lazyNumber: Int by lazy {
100
} //사용 전까지는 100이 할당되어있지 않음
println("숫자는 ${lazyNumber} 입니다.") //실제 사용하는 이 시점에 100이 할당됨
'안드로이드 > Kotlin' 카테고리의 다른 글
[안드로이드][Kotlin] Collections (List, Map, Set) (6) | 2023.08.11 |
---|---|
[안드로이드][Kotlin] Scope Functions (Apply, Also, Let, With, Run 함수) (0) | 2023.08.03 |
[안드로이드][Kotlin] 액티비티 간의 데이터 전달 (+registerForActivityResult() 사용) (1) | 2023.08.01 |
[안드로이드][Kotlin] Firebase SDK 추가 (0) | 2023.02.23 |