Kotlin

lateinit, lazy

kakaroo 2022. 3. 26. 02:11
반응형

kotlin logo

 

lateinit

 

코틀린에서는 클래스 멤버내의 프로퍼티 변수는 선언 이후, 반드시 초기화를 하거나 init 블럭 내에서 초기화를 해야 합니다.

초기화 값이 마땅치 않을 때 nullable 타입형태로 null 로 초기화 한 뒤, 실제 데이터로 값을 적용하는 것도 일종의 초기화 방법입니다.

 

위 방법 대신,,

lateinit 키워드를 사용하면 초기화를 미룰 수 있습니다.

하지만, lateinit 을 사용하기 위해서는 다음과 같은 제약이 있습니다.

  • var 로 선언한 프로퍼티에만 사용할 수 있습니다.
  • 클래스 몸체에 선언한 프로퍼티에만 사용할 수 있습니다. (주생성자의 프로퍼티에는 사용할 수 없습니다.)
  • lateinit 사용한 변수는 setter()/getter()를 사용할 수 없습니다.
  • 코틀린에서 기본적으로 제공하는 primitive type (Int, Boolean, Double)에도 사용할 수 없습니다.
  • null 허용 프로퍼티에는 사용할 수 없습니다.

 

에러 예)

 

class User2() {
    lateinit var name
        get() = field.uppercase()
        set(value) {
            field = "Hello " + value
        }
}

lateinit 사용한 변수는 setter()/getter()를 사용할 수 없습니다

 

class User3 {
    lateinit var name: String
}

 

초기화 하지 않고, 접근하는 경우 런타임 에러가 발생합니다.

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

val user3 = User3()
println(user3.name)

 

 

안드로이드의 사용 예)

class MainActivity : AppCompatActivity() {

    lateinit var mPref: SharedPreferences
    
    override fun onCreate(savedInstanceState: Bundle?) {    	
    	mPref = PreferenceManager.getDefaultSharedPreferences(this)
        if(::mPref.isInitialized) {
        	mPref.xxxxxx
        }
   }
}

 

 

초기화 미루기 : lazy

프로퍼티의 초기화를 프로퍼티의 이용시점으로 미루는 방법입니다. 실제 프로퍼티를 이용하는 시점에 초기화 할 수 있습니다.

lazy 사용은 다음의 규칙이 있습니다.

  • 호출 시점에 초기화가 진행됩니다.
  • val로 선언한 프로퍼티에만 사용이 가능합니다.
  • 클래스 몸체 이외에 최상위 레벨에서도 사용이 가능합니다.
  • 기초타입에도 사용이 가능합니다.

 

 

class User2 {
    val name: String by lazy {
        println("name is initiaiized by lazy")
        "kkang"
    }
    val age: Int by lazy {
        println("age is initiaiized by lazy")
        20
    }
    init {	
    	//name = "jeong"	//compile error;
        //name은 by lazy로 선언되었기 때문에 init 블럭내에서 프로퍼티에 값을 설정할 수 없다.
        println("init block")
    }
    constructor() {
    	//age = 30	//compile error;
        //age는 by lazy로 선언되었기 때문에 init 블럭내에서 프로퍼티에 값을 설정할 수 없다.
        println("constructor")
    }
}

 

val user2 = User2()
println("1st + ${user2.name}")
println("2nd + ${user2.age}")

//output
init block
constructor
name is initiaiized by lazy
1st + kkang
age is initiaiized by lazy
2nd + 20

 

안드로이드에서는 실제 아래와 같이 많이 사용됩니다.

private val mediaPlayer: MediaPlayer by lazy {
    MediaPlayer.create(this. R.raw.iloveyou)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    mediaPlayer.start() //호출되는 시점에 초기화가 된다.
}

 

 

nullable 타입형태로 선언해서 null로 선언하고, 나중에 필요할 때 값을 입력하면 되지 라고 생각할 수도 있겠지만, null을 대입할 수 없는 프로퍼티를 굳이 null 허용으로 선언할 필요는 없습니다.

코틀린은 null 처리가 엄격합니다. null 을 대입하지 않는 프로퍼티에 단지 초기화 시점을 미루기 위해 null 허용으로 선언할 필요는 없습니다.

반응형

'Kotlin' 카테고리의 다른 글

collection  (0) 2022.03.27
reduce, fold  (0) 2022.03.26
Scope 함수(범위 지정 함수 - apply, with, let, also, run)  (0) 2022.03.26
backing field <custom getter(), setter() 설정>  (0) 2022.03.26
val, const val  (0) 2022.03.25