[Kotlin] lateinit vs by lazy

유정현·2024년 4월 25일
1

처음 코틀린을 사용하기 시작했을 때 다음과 같이 변수 선언을 많이 했다.

var temp: String? = null

하지만 이렇게 하면 초기화를 한 후에 non-null이 되게 하고 싶은 경우나 초기화를 한 후에 값이 변경되지 않도록 하고 싶은 경우가 있을 수 있다. 이때 사용하는 것이 늦은 초기화이다.

늦은 초기화

클래스 안에서 변수를 선언한 후에 나중에 변수를 실제로 사용하는 시점에 값을 초기화해 사용하는 것을 의미한다.

Java의 경우, 다음과 같이 변수를 선언만 하면 null이 기본값으로 들어간다.

static String a;
    public static void main(String[] args) {
        System.out.println(a); // null
    }

하지만, Kotlin의 경우에는 초기화가 필수이다.

lateinit

lateinit var a: String

fun main() {
    a = "늦은 초기화"
    print(a)
}

lateinit은 다음과 같은 특징이 있다.

  • var 키워드와 같이 사용한다
  • null을 허용하지 않는다
  • 생성자에서 사용 불가능하다
  • Int, Double, Float와 같은 Primitive Type에 대해서는 사용할 수 없다

by lazy

lateinit var a: String
val b: Int by lazy { a.length }

fun main() {
    a = "늦은 초기화"
    print(a) // 늦은 초기화
    print(b) // 6
}

변수 b에 a의 length를 넣으려고 하는데 a = "늦은 초기화"로 초기화가 된 후에야 a의 length를 알 수 있다. 이때 by lazy를 사용해 a가 초기화된 후, print(b)가 실행될 때 변수 b가 처음 사용되기 때문에 이때 변수 b가 초기화된다.

by lazy는 다음과 같은 특징이 있다.

  • val 키워드와 같이 사용한다
  • null을 허용한다
  • 생성자에서 사용 불가능하다

만약 초기화를 하지 않는다면..??

컴파일 단계에서 UninitializedPropertyAccessException이 발생한다.


기타

궁금한 점이 생겼다.
1. lateinit은 초기화하기 전까지 무슨 값이 들어있을까?
2. lateinit은 왜 Primitive Type이 불가능할까?
3. 왜 lateinit은 val 키워드를 사용하면 안될까?

lateinit var a: String

fun main() {
    a = "늦은 초기화"
    print(a) // 늦은 초기화
}

위의 코드를 java로 decompile하면 알 수 있다.

1. lateinit은 초기화하기 전까지 무슨 값이 들어있을까?

변수 var10000가 null이면 예외를 발생시키고 값이 있으면 그대로 반환함을 알 수 있다. 즉, 초기화하기 전까지는 null이 들어가있다!

2. lateinit은 왜 Primitive Type이 불가능할까?

Kotlin은 Primitive Type와 Wrapper Type 구분이 없다.
Java에서 Primitive Type에는 int, boolean, float 등이 있고, Wrapper Type은 Primitive Type을 객체로 변환한 클래스로 Integer, Boolean, Float 등이 있다.

위의 java 코드를 보면 해당 변수가 초기화 되었는지의 여부를 null로 판단하고 있다. 하지만 Primitive Type은 null일 수 없기 때문에 lateinit은 Primitive Type에 대한 지원을 하지 않는다.

3. 왜 lateinit은 val 키워드를 사용하면 안될까?

class P {
    var b: String = "선언"
}

위 코드를 java로 decompile하면 다음과 같다.

변수 b가 var 타입이기 때문에 getter와 setter가 구현되어 있다.

class P {
    val b: String = "선언"
}

val로 한 경우에는 어떻게 될까?

값을 변경할 수 없기 때문에 setter이 없다. 위에서 lateinit을 활용한 kotlin을 java로 디컴파일한 코드를 보면, getter 메서드만 있고 setter 메서드는 없다. 즉 setter 메서드가 구현되어 있지 않기 때문에 val과 함께 사용 불가능하다.

0개의 댓글

관련 채용 정보