코틀린 lateinit vs lazy

Lee Jun Hyeong·2022년 12월 30일
0

Kotlin 톺아보기 🙂

목록 보기
2/4

📌 lateinit, 늦은 초기화

코틀린에서는 변수를 선언할때 객체를 바로 할당하지 않는 경우에 기본적으로 컴파일이 되지 않는다. 경우에 따라 변수만 일단 선언하고 늦게 초기화를 해야할때 lateinit 프로퍼티를 사용할 수 있다.

lateinit은 일단 미리 변수를 선언해놓고 이후에 값을 할당한다.
var 변수만 사용 가능하고,
기본 자료형(Primitive Type) Int, Boolean, Double, Char 등등의 자료형에는 사용할 수 없다.
또한 getter와 setter도 사용할 수 없다.

lateinit 초기화 확인 여부는 변수 이름 앞에 ::(콜론2개)를 붙이고 .isInitialized를 사용하면 상태를 알 수 있다.

lateinit var text : String

fun main() {
    println(checkLateInit())
    text = "할당 된 값 있음 !!"
    println(checkLateInit())
}

private fun checkLateInit() : String{
    if (::text.isInitialized) return text
    return "할당 된 값 없음"
}

변수를 선언한 뒤 초기값 할당 전에 lateinit 변수를 사용하면 아래와 같이 초기화되지 않았다고 Exception이 발생한다.

Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property b has not been initialized

📌 lazy, 초기화 지연

코드상으로는 선언시에 즉시 객체를 생성 및 할당하여 변수를 초기화하는 것처럼 보이지만, 실제 실행시에는 val 변수를 사용하는 시점에 초기화가 진행하여 코드의 실행시간을 최적화할 수 있도록 한다.

변수를 실행하는 시점까지 초기화를 자동으로 늦춰주는 지연 대리자 속성(lazy delegate properties)을 가진 lazy는 lateinit과 달리 val 변수를 사용해야한다.
lazy는 람다함수 형태의 초기화 함수를 사용하는 형태로 val 변수를 선언한 뒤, by lazy를 붙이고 람다함수를 정의해주면 된다.
람다함수로 초기화가 진행되므로 함수안에 여러개의 구문이 들어갈 수 있으며 맨 마지막 구문의 결과가 변수에 할당된다.

val number : Int by lazy {
    println("초기화를 합니다.")
    7
}
fun main() {
    println("코드를 시작합니다")
    println("1 -- $number")     //호출시에 초기화 진행
    println("2 -- $number")     //이미 초기화해서 다시 초기화 구문 실행하지 않음
}

위 코드에선 number 변수를 lazy로 선언하고 출력 하는 시점에 초기화를 진행한다. 첫번째 호출땐 "초기화를 합니다"라고 출력되지만 두번째 호출때는 "초기화를 합니다"라는 출력문이 나타나지 않는다. 이미 초기화를 진행했기 때문에 두번 초기화를 하지 않는다. number 변수는 값을 다시 초기화할 수 없어서 7이라는 값이 고정된 변수로 쓰이게 된다.

📌 정리

코틀린에서 lateinit과 lazy로 초기화를 늦게하는 하도록 하는 이유는 메모리 사용을 좀더 유용하게 쓸 수 있기 위함이다.

보통 class에서 변수를 초기화하면, 클래스 생성 시 해당 변수도 함께 생성되며 초기화된다.
클래스 객체를 생성할 때 마다 해당 변수도 함께 초기화되기 때문에 바로 사용할 수 있다는 장점이 있다.

하지만 해당 변수를 바로 사용하지 않거나 꼭 사용하는 경우가 아니라면 오히려 클래스 생성마다 해당 변수를 만들고 초기화 하는 것이 시간적, 메모리적 낭비이다.
또한, 전역 변수를 선언하기 위해 굳이 = null 을 번거롭게 해야 할 경우도 종종 있다.


참고
https://jerryjerryjerry.tistory.com/85
https://maivve.tistory.com/156
profile
"왜" 사용하며, "어떻게" 사용하는지에 대해

0개의 댓글