Kotlin, Null 처리
Null 허용 (? 연산자)
코틀린(Kotlin)에서는 기본적으로 Null값을 허용하지 않으므로, 기본적으로는 모든 객체가 생성과 동시에 값을 초기화 필요
초기화하지 않아 에러가 발생하는 예시
val a :String // Error, 초기화 필요
Null 값으로 초기화해서 에러 발생하는 예시
val a :String = null // Error, 기본적으로 Null값 허용 x
? 키워드 - @Nullable
변수의 자료형 오른쪽에 ? 연산자를 명시적으로 사용하면, 해당 변수는 Null값을 허용하는 의미로 에러 미발생
val a :String? = null // OK, ? 키워드로 @Nullable 의미
안전한 호출 (?. 연산자)
?. 연산자는 Null Safe operator의 의미
메서드 호출 시 점(.) 연산자 대신 (?.)를 사용하면 해당 변수/객체가 Null이 아닌 경우에만 호출
{ 변수/객체?.메서드() } 형식으로 사용, 해당 변수/객체가 Null이 아니면 메서드를 호출하고, Null이면 null을 반환
Null이 아닐때 메서드 호출결과
str.toUpperCase() // TEST CODE, 대문자로 변환
Null일때 메서드 호출 결과
str2?.toUpperCase() // null 반환
안전한 호출 '?.'키워드를 사용하면 if문을 정말 간단하게 줄여서 사용이 가능
val str :String? = null
// str이 null이 아닌지 검사, true면 메서드 호출, 아니면 null 반환
println(if (str != null) str.toUpperCase() else null)
println(str?.toUpperCase())
엘비스 연산자 (?:)
안전한 호출(?.)시 null이 아닌 사용자 정의값을 반환하고 싶을 때 (?:)엘비스 연산자를 함께 사용.
기본적으로 안전한 호출(?.)에서 null이면 null을 반환, 그 반환값을 지정해주는 연산자
null이 아니면 "초기화하시오"를 출력하는 예시
ex) if ( str != null ) str.toUpperCase() else "초기화하시오." - 동일한 방법
val str :String? = null
// 기본 안전한 호출만 사용시
println(str?.toUpperCase()) // null 출력
// str이 null이 아니면 toUpperCase() 호출, null이면 ?: 연산자 뒤를 호출
println(str?.toUpperCase() ?: "초기화하시오." // "초기화하시오." 출력
Null값이 아님을 보증 (!!)
@NotNull 의미로 해당 변수가 Null값이 아님을 보증해줘서 null값이 허용되는 변수를 대입할 수 있도록 하는 연산자(!!)
val name :String? = "김루피" // Null일수도 있는 변수에 "김루피" 할당
val name2 :String = name // Error, name은 Null일수 있기에 에러 발생
val name3 :String? = name // OK, name3도 Nullable한 변수이기에 할당 가능
val name4 :String = name!! // OK, name!!로 name이 null이 아님을 보증
만약 (!!)연산자로 null이 아님을 보증했지만 null값이라면 실행시 NPE예외 발생
늦은 초기화 - lateinit
변수/객체의 값을 나중에 초기화할 경우가 필요할 때 사용하는 키워드(lateinit)
변수선언 앞부분에 추가하여 사용 { lateinit var 변수명 :자료형 } 방식으로 늦은 초기화 선언 후 나중에 초기화를 진행
초기화를 하지 않고 변수를 접근하면 null 값을 참조하게 되면서 NPE예외로 앱종료 발생
// 기본 변수 사용
var a :String // Error, 초기화 필요
// lateinit 키워드 사용
lateinit var str :String
println("%{str} 출력결과") // Error, NPE예외 발생 (Null 참조)
str = "TEST"
println("%{str} 출력결과") // "TEST 출력결과" 출력
lateinit 키워드 사용 조건
- var 변수에서만 사용
- Null 값으로 초기화 불가
- 초기화 전에는 변수 사용 불가 (NPE예외 발생)
- Int / Long / Double / Float 자료형은 사용 불가
늦은 초기화 - lazy
lateinit이 var변수의 늦은 초기화라면 lazy는 값을 변경할 수 없는 val(상수)에 사용하는 키워드
변수 자료형 뒤에 추가해서 사용 " val 변수명 :자료형 by lazy { 초기화 블럭 } " 사용 방식
by lazy 키워드의 초기화 블럭은 해당 변수가 처음 호출될때 실행되고, 그 이후 호출에는 초기화 블럭 실행 X
val str :String by lazy {
println("초기화") // 함수 호출도 가능
var temp = "test code"
temp.toUpperCase() // 초기화 블럭의 마지막 값이 str에 저장되는 값
}
// str을 처음으로 호출하는 시점에 lazy 내부 초기화 블럭 수행 (1~5 Line)
println("$str") // 초기화; TEST CODE 출력
println("$str") // TEST CODE 출력