코틀린에선 NullPointerExeption을 방지하는 Null Safety를 지원합니다. Null Safety란 개발자가 타입 시스템이 Null이 가능한지 아닌지 변수 선언시 타입뒤에 ?를 붙혀 Null을 허용하도록 해주는 기능입니다. 그런데 코드 상에서는 null이 될 수도 있지만 실제 동작 중에는 null이 안되는 경우가 있습니다.
class MainActivity: AppCompatActivity() {
var testString: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
testString = "테스트"
}
}
위와 같이 testString을 전역변수로 선언 후 onCreate()에서 초기화를 시켜주는 코드입니다. 이때 onCreate()에서 값이 항상 초기화되기 때문에 안전한 코드라고 볼 수 있습니다. 그러나 이때도 ?를 표시해야 하는 불편함이 있습니다. 그래서 프로퍼티의 초기화를 필요한 시점에서 하는 기법을 사용하게 됩니다. kotlin에서는 lateinit 과 by lazy 2가지 지연 초기화 방법이 있습니다.
- var 프로퍼티에서 사용가능
- null을 허용하지 않음
- get() set() 사용이 불가능함
- 생성자에서 사용 불가능
class MainActivity: AppCompatActivity() {
lateinit var testString: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
testString = "테스트"
}
}
위와 같이 변수 앞에 lateinit 키워드를 붙히고 변수의 자료형을 명시해줍니다. lateinit은 mutable 변수에만 사용이 가능하기 때문에 var 타입의 변수에만 사용이 가능합니다.
- val 프로퍼티에서 사용 가능
- null을 허용함
- get() set() 사용이 불가능함
- 생성자에서 사용 불가능
class MainActivity: AppCompatActivity() {
val testString: String by lazy {
"테스트"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
println(testString)
}
}
by lazy는 해당 변수가 호출되는 시점에 초기화를 하겠다는 의미입니다.
by lazy는 lateinit과 다르게 immutable변수에만 사용이 가능하기 때문에 val 타입의 변수에만 사용이 가능합니다.
1. 반드시 초기화를 안해도 되는 경우 (null 허용)
val test by lazy { "초기화 안합니다."}
fun main() {
println("test 선언을 안했어요")
}
//출력: test 선언을 안했어요 -> null point exception는 일어나지 않습니다.
2. 최초 초기화 후 다시 초기화 할일이 없을 때 (val) 비교 lateinit
lateinit의 경우 아래와 같이 var (mutable) 이기 때문에 여러번 재 초기화가 가능합니다.
lateinit var lateTest:String
fun main() {
lateTest = "1번째 초기화"
println("1 :$lateTest")
lateTest= "2번째 초기화"
println("2 :$lateTest")
}
반면 by lazy{}의 경우 재 초기화가 안됩니다.
https://kotlinlang.org/docs/properties.html#late-initialized-properties-and-variables
https://kotlinlang.org/docs/delegated-properties.html#lazy