프로그래밍/Kotlin

[코틀린 / Kotlin] lazy 와 lateinit 를 활용한 지연 초기화

pupu91 2022. 10. 20. 16:38
반응형

 

lazy

해당 속성 값을 사용하는 시점에 값을 초기화 하는 편이 합리적이다 라는 생각으로 만들어진 키워드로 
속성에 접근하는 시점에 값의 초기화 작업이 이루어지게 하는 키워드

 

lazy 키워드를 이용한 속성 값 지연 초기화

class LazyClass(var x: Int){

    /* lazy는 var로 선언할 수 없다.
    * 호출 시점에서 초기화가 이루어지며 최초 한 번만 초기화 된다.
    * LazyClass만들 때 같이 생성 되는게 아니라 나중에 lazyValue1를쓰고자 하는 시점이 왔을때 안의 구문 동작됨*/
   
   val lazyValue1 by lazy { 
        
        println("lazy 람다식 내부에서 속성값 초기화 진행")
        var s = "   HELLO    "
        s.trim()
    }

    val lazyValue2 by lazy {
        x * 2
    }

    val constHeavyProperty by lazy{
        println("시간이 오래 걸리고 메모리 사용량이 많은 속성값 초기화 진행")
        Thread.sleep(1000)
        Array<Byte>(1024 * 1024 * 100) {0}
    }
}

fun main(){

    var lazyClass = LazyClass(10)
    println("lazyClass 인스턴스 생성!")
   
    /* 처음으로 속성에 접근하는 순간 람다식 내부의 명령어가 실행되어 속성값이 초기화 됨 */
    println(lazyClass.lazyValue1)
    
    /* 이후 속성에 여러번 접근해도 출력문은 실행되지 않음(이미 기존에 초기화 된 값에 접근)*/
    println(lazyClass.lazyValue1)
    println(lazyClass.lazyValue1)

    println(lazyClass.lazyValue2) //사용하는 시점에 초기화 진행

    // 시간이 걸리고 메모리 사용량이 많은 경우 객체 생성 시보다 호출 시점에 초기화 하는 것이
    // 성능적으로 효율적일 수 있다.
    println(lazyClass.constHeavyProperty)
}

출력 결과
lazyClass 인스턴스 생성!
lazy 람다식 내부에서 속성값 초기화 진행
HELLO
HELLO
HELLO
20
시간이 오래 걸리고 메모리 사용량이 많은 속성값 초기화 진행
[Ljava.lang.Byte;@47f6473

 

반응형

lateinit

객체 타입만 가능
당장 값을 대입하기 어려운 상황에서 나중에 해당 속성에 접근하기 전까지는 속성 값이 초기화 되었음을 보장하고 싶은 속성에 사용한다.

 

lateinit 키워드를 이용한 속성 값 지연 초기화

class LateInitClass{

    /* lateinit은 primitive 타입을 지원하지 않음 - 객체 타입만 가능
    * var로만 선언 가능하고 val 사용 불가 */
    lateinit var obj: PropertyObject

    fun initMyObject(value: PropertyObject){
        obj = value //값을 초기화
    }

    fun useMyObject(){

        obj.func() //늦게 초기화 되는 속성 값에 접근
    }
}

class PropertyObject{
    fun func(){
        println("from PropertyObject Function")
    }
}

fun main(){

    var lateInitClass = LateInitClass()
    // 적절한 초기화 과정 없이 호출할 겨우 에로 발생 -  lateinit property obj has not been initialized
    //lateInitClass.useMyObject()

    lateInitClass.initMyObject(PropertyObject()) //초기화 수행//PropertyObject()타입을 전달 받아서 값을 초기화
    lateInitClass.useMyObject()   //초기화한 후 안전하게 사용 가능
}
반응형