[Kotlin] lateinit? lazy?

LTT·2024년 10월 16일

lateinit?


late(늦은) init(초기화), 즉 초기화를 늦게하는 변수이다.

코드부터 살펴보자.

fun test() {
	val a
    // ... 뭔가 로직1
    if(로직1 == true) a = "hello"
    else a = "world"
    // ... 뭔가 로직2
    println(a)
}

일단 위의 코드를 실행하면, 아니 실행할 수도 없다.

"This variable must either have a type annotation or be initialized" 가 당신의 발목을 잡을 것이기 때문이다.

이렇게 로직1번을 수행하고 나서 a를 결정해야 될 경우 여간 난처하지 않을 수가 없다.

"val a: String? = null 로 선언해 놓고, 나중에 수정하면 되잖아."

하지만, 얘는 나중에 무조건 사용할 건데, 위험하게 null로 놔두자니 여간 찝찝한게 아니다.

이래서 필요한 것이 lateinit이다.

fun test() {
	lateinit var a: String
    // ... 뭔가 로직1
    if(로직1 == true) a = "hello"
    else a = "world"
    // ... 뭔가 로직2
    println(a)
}

이렇게 초기화를 늦게하는 변수라는 것을 선언해주고, 사용할 경우 문제가 깔끔하게 해결된다.

심지어 lateinit은 var과 함께 사용해야 하기 때문에, 초기화 이후에도 값을 계속 바꿀 수 있다.

"그럼 lateinit해놓고 초기화 안하는 경우도 문제 아니야?"

맞다. 그래서 lateinit으로 선언해놓고 초기화하지 않는 경우, 컴파일 단계에서 에러를 알려주기 때문에, 잠재적인 에러들을 나름 방지할 수 있다는 장점이 있다.

lazy?


자 그러면, lazy는 또 무엇인가. 코드부터 봐보자

fun test() {
	lateinit var a: String
    val aLength: Int by lazy {
    	a.length
    }
    // ... 뭔가 로직1
    if(로직1 == true) a = "hello"
    else a = "world"
    // ... 뭔가 로직2
    println(a)
    println(aLength)
}

by lazy 라는 구문을 사용했다. 잘 보면, 아직 초기화를 하지 않은 a의 length를 사용하여 지정을 해준 모양이다.

by lazy 는 선언 당시에는 초기화하기 힘들지만, 사용하고자 하는 값이 초기화 된 이후에 값을 채워넣고 싶을 때 사용한다.

따라서, a가 초기화된 후에 a의 길이만큼 자동으로 a의 길이만큼 자동으로 초기화를 가능하게 해준 부분이 저 by lazy 인 것이다.

정리


정리하자면, 둘 다 나중에 초기화하기 위해 사용하는 친구들이다.

  • lateinit
    • 값 이후로 변경 가능 (var을 사용)
    • 초기화 이후, 값이 계속 바뀔 수 있는 상황에 사용
  • lazy
    • 값 이후로 변경 불가 (val을 사용)
    • 초기화 이후, 값이 바뀔일 없이 읽기에만 쓰이는 상황에 사용
profile
개발자에서 엔지니어로, 엔지니어에서 리더로

0개의 댓글