본문 바로가기

코틀린 Kotlin

kotlin (6) - lateinit 과 by lazy 용도 간단 정리

내일 토요일을 맞기 전에 java, kotlin , oop, solid , mvvm,mvc,mvp , AAC, android 등등을 한번에 복습을 해봤습니다. 과거에 공부했던 것들을 다시 보니 안보였던 부분들이 다시 보이기도하고 감회가 참 새로운거 같습니다. 이래서 영화를 여러번 돌려보나봅니다. 

 

아무튼 마음 같아선 모두 한꺼번에 정리하는 글을 적고 싶지만 아쉽게도 시간은 한정적이네요

 

0. 지연 초기화 (lazy initialization) 

프로퍼티의 초기화를 필요한 시점에서 하는 기법입니다. 

그래서 소프트웨어 성능이나 효율의 이점을 얻을 수 있습니다. 

kotlin에서는 2가지 지연 초기화를 지원합니다. lateinit 과 by lazy입니다.

 

1. lateinit

- var 프로퍼티에서 사용가능

- null을 허용하지 않음

- get() set() 사용이 불가능함

- 생성자에서 사용 불가능 

 

코틀린 같은 경우 null 허용 표시를 골라서 해야되기 때문에 변수가

null 허용 객체라면 항상 변수!! 혹은 변수? 이런식으로 사용해야합니다. 

public class MyTest {
    var subject: TestSubject?

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {
        subject!!.method()  // dereference directly
    }
}

클래스 안에 null 허용 객체를 만들면 이 객체를 사용할 때

항상 변수!! or 변수? 를 표시하는것이 번거로울 수 있습니다.

그럴때 lateinit을 사용하는게 차라리 편합니다. 

public class MyTest {
    lateinit var subject: TestSubject

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {
        subject.method()  // dereference directly
    }
}

위와 같이 사용할 수 있습니다.

그러면 null를 허용하지 않으면서 null 허용표시 없이 사용할 수 있습니다.

 

또한 lateinit var 객체는 초기화되기 전에 프로퍼티를 사용하면 

 프로퍼티가 초기화되지 않았다는 사실을 명확하게 식별하는

특수 예외가 발생하기 때문에 더 정확한 디버깅이 가능합니다.

 

isInitialized

그리고 isInitialized를 사용해서 프로퍼티가 초기화 되었는지 확인 할 수 있습니다.

if (foo::bar.isInitialized) {
    println(foo.bar)
}

 

2. by lazy

- val 에서 사용 가능

- get() set() 을 지원하지 않음

- 널 허용 

- 클래스 생성자에서 사용 불가

public class MyTest {
     val subject by lazy{TestSubject()}

    @Test fun test() {
        subject.method() 
    }
}

by lazy()는 늦게 초기화할 내용을 미리 적어놓고 해당 by lazy를 선언한 프로퍼티를 사용시 초기화가 됩니다. 

위 코드에서 subject.method()가 첫 초기화를 해주는 부분 이면서 method()를 사용하는 부분 입니다.

lateinit 과 달리 null을 허용하기 때문에 까먹고 사용하지 않아도 null예외가 발생하지 않습니다.

 

 

 

3. by lazy를 사용하는 경우 (vs lateinit)

 

1) 반드시 초기화를 안해도 되는 경우 (null 허용)

val test by lazy { "test" }
fun main() {
    println("초기화 안함")
}
//출력: "초기화 안함"  -> null point 예외는 일어나지 않습니다.

2) 최초 초기화 후 다시 초기화 할일이 없을 때 (val)

 

lateinit의 경우 아래와 같이 var (mutable) 이기 때문에 여러번 재 초기화가 가능합니다.

lateinit var lateTest:String
fun main() {
    lateTest = "1번째 초기화"
    println("1 :$lateTest")
    lateTest= "2번째 초기화"
    println("2 :$lateTest")

}

 

반면 by lazy{}의 경우 재 초기화가 안됩니다.

 

이상 간단한 지연 초기화 정리였습니다. 

 

원래 by lazy{} 가 작동하는 원리에 대해 포스팅 하려고 했으나 상세히 적으려면

포스팅 양이 엄청 많아지므로 다음 기회에 작성하도록 하겠습니다.