tonykang22 / study

0 stars 0 forks source link

[Kotlin & Spring] 07. 지연초기화 #116

Open tonykang22 opened 1 year ago

tonykang22 commented 1 year ago

지연초기화

지연초기화란


지연초기화는 많은 상황에서 쓰이고 있다.

public class Java_Singleton {

        privagte Java_Singleton() {
                /* do nothing */
        }

        public Java_Singleton getInstance() {
                return LazyHolder.INSTANCE;
        }

        private static class LazyHolder {
                private static final Java_Singleton INSTANCE = new Java_Singleton();
        }
}





코틀린에서 제공되는 지연초기화 방식

by lazy

fun getHello() = "안녕하세요"

fun main() { val helloBot = HelloBot()

    //...
    helloBot.greeting = getHello()
    helloBot.sayHello()

}


<br>

- lazy 함수 내부에 초기화 로직을 구현한다.
``` kotlin
class HelloBot {

        val greeting: String by lazy { getHello() }

        fun sayHello() = println(greeting)
}

fun getHello() = "안녕하세요"

fun main() {
        val helloBot = HelloBot()

        //...
        helloBot.sayHello()
}
// 안녕하세요


fun getHello = "안녕하세요"

fun main() { val helloBot = HelloBot()

    //...
    helloBot.sayHello()
    helloBot.sayHello()

} // 초기화 로직 수행 // 안녕하세요 // 안녕하세요


<br>

- `by lazy`는 기본적으로 멀티스레드 환경에서도 안전하게 동작하도록 설계되었다.
    * `by lazy` 내부에서 스레드에 대한 동기화 처리를 해주기 때문이다. (내부 코드 확인)
    * 기본 모드는 `LazyThreadSafetyMode.SYNCHRONIZED`와 동일하다.
``` kotlin
fun main()
        val helloBot = HelloBot()

        //...
        for (i in 0..5) {
                Thread {
                        helloBot.sayHello()
                }.start()
        }
}
// 초기화 로직 수행
// 안녕하세요
// 안녕하세요
// 안녕하세요
// 안녕하세요
// 안녕하세요
// 안녕하세요




lateinit



fun main() { val test = 7_LateInit() test.printText() } // 안녕하세요


<br>

- 초기화 전에 사용하면 어떻게 될까?
    * 특정 DI와 같이 외부에서 초기화를 해주는 경우를 염두해두고 만든 기능이기 때문에, 초기화 전에 사용하더라도 컴파일 오류가 발생하지 않는다.
``` kotlin
class `7_LateInit` {
        lateinit var text: String

        fun printText() {
                println(text) // 초기화 전에 사용
                text = "안녕하세요"
        }
}

fun main() {
        val test = `7_LateInit`()
        test.printText()
}
// UninitializedPropertyAccessException



fun main() {
val test = 7_LateInit() test.printText() } // 안녕하세요


<Br><br>

- `isInitialized`는 내부에서는 사용할 수 있지만 외부에서는 사용할 수 없다.

fun main() { val test = 7_LateInit() test.printText() test.isInitialized // 컴파일 오류 }