0101011001010111

kotlin4-4 지연 초기화 본문

Kotlin/스파르타_코틀린 문법

kotlin4-4 지연 초기화

[진주] 2023. 8. 2. 10:09
728x90
반응형

지연초기화

: 변수나 상수의 값을 나중에 초기화 할 수 있어요.

 

▼설명

코틀린은, 클래스를 설계할 때 안정성을 위해 반드시 변수의 값을 초기화 할 것을 권장해요.

ㄴ 우리가 클래스 만들때 항상 = 하고 공백이라도 넣어줬던거 기억나시죠? 원래 항상 그렇게 해야하는데...

 

클래스를 설계할 때 초기의 값을 정의하기 '난처'해서 나중에 대입하기 위한 문법이예요.

ㄴ 초기값을 처음에 지정하기가 난처한 경우에 쓰는게 지연 초기화예요.

 

코틀린은 지연초기화 또는 늦은초기화를 위해 lateinit, lazy 키워드를 활용해요.

 

저사양으로 제한되어있는 환경에서는 메모리를 더욱 효율적으로 사용할 수 있어요

ㄴ 항상 처음부터 값이 들어있는 것 보다는, 실제로 메모리를 효율적으로 관리하면서,

    필요할 때 값을 초기화 해주는 게 더욱 좋겠죠?

 


예시▼

변수의 지연초기화(lateinit)

name변수 값을 초기에 정의하기 어렵기 때문에 lateinit을 사용해요.

ㄴ 물론 """와 같이 공백으로 처리 할 수 있지만, 가독성 측면에서 좋은 행위가 아닙니다.

fun main(){
    var s1 = Student()
    s1.name = "참새"
    s1.displayInfo()

    s1.age = 10
    s1.displayInfo()
}

class Student {
    lateinit var name:String
    var age:Int = 0

    fun displayInfo() {
        println("이름은: ${name} 입니다.")
        println("나이는: ${age} 입니다.")
    }
}

 

Student라는 클래스가 있고, 

그 안의 var name:String = "" << 이렇게 했었는데, 

lateinit var name:String

lateinit이라는 걸 붙이고 나서 = 하고 초기화를 하지 않고도 사용할 수 있어요.

 

위 코드를 실행해보면, 

 

이걸 그려보자면

 


2분 ~ 3분 29

변수가 초기화 되었는지 확인해보는 방법

먼저, 변수를 사용하기 전에 초기화 되었는지 확인해야 안정성을 높일 수 있습니다.

isInitialized를 활용해서 값이 초기화 되었는지 확인할 수 있다.

(값은 true/false로 줍니다)

 

사용할 때는 값이 아니라 참조형태로 사용해야하기에 this::또는 ::을 붙여요.

▼ 예제

fun main(){
    var s1 = Student()
    s1.name = "참새"
    s1.displayInfo()

    s1.age = 10
    s1.displayInfo()
}

class Student {
    lateinit var name:String
    var age:Int = 0

    fun displayInfo() {
        if(this::name.isInitialized) {
            println("이름은: ${name} 입니다.")
            println("나이는: ${age} 입니다.")
        } else {
            println("name변수를 초기화해주세요.")
        }
    }
}

-if(this::name.isInitialized) 여기서 this를 삭제해도 올바르게 작동한다.

 

결과값 : 

이미 초기화가 잘 되었기에, 해당 결과값이 나온다.

 

만약, 해당 코드를 안쓰고 초기화가 안됐는데 코드를 실행했다면 그건 또 예외가 발생하고, 

예외처리를 위한 틀에 객체를 또 묶어서 코드가 길어지고,

성능이 저하돼요.

하지만, if(this::name.isInitialized)  요거 한줄만 추가해서 조건을 검사하면 더욱 간결하게 코드를 작성할 수 있겠죠?

 

>> 즉, 머리가 안좋으면 몸이고생함....ㅠ 알아두자 이거 ㅠ 


 

상수의 지연초기화(lazy)

상수는 lazy를 통해 지연초기화를 수행해요.

- 상수를 사용하는 시점에 값을 대입하고 초기화가 수행돼요.

fun main(){
    var s1 = Student()
    s1.name = "참새"
    s1.displayInfo()

    s1.age = 10
    s1.displayInfo()
}

class Student {
    lateinit var name:String
    var age:Int = 0
    val address: String by lazy {
        println("address 초기화")
        "seoul"
    }

    fun displayInfo() {
        println("이름은: ${name} 입니다.")
        println("나이는: ${age} 입니다.")
        println("주소는: ${address} 입니다.")
    }
}
val address: String by lazy {
    println("address 초기화")
    "seoul"
}

자, Student 클래스에서 address를 상수로 만들건데, lazy로 만들거예요.

String이고 lazy로 만들고

 

println("address 초기화") << 초기화가 되었을 때 실행될 값 

"seoul" << 초기화 값

 

을 넣어줬습니다.

 

 

 

lazy : 상수를 사용하는 시점에 값을 대입하고 초기화가 수행돼요.

자, 사용할 때 초기화 된다고 했죠? 

 

▼결과값

s1.name = "참새"

s1.displayInfo()

자, 처음 s1.displayInfo()를 부를때 name입력된것 나오고, 나이는 아직 순서가 입력이 안되었으므로, 0 이다.

그리고 

처음 s1코드를 부를때 상수 val address가 초기화 되었으므로,

address초기화 문구가 나온 후, 주소는 seoul입니다 라고 출력된다.

 

자 두번째  s1.displayInfo() 실행시, 

age가 10인 값을 받았고, 이미 name값은 위에서 받았고,  주소는 이미 'seoul'로 초기화 되었기 때문에

address초기화 문구가 안나오고 바로 주소는 서울입니다 로 나오게 된다.

 


자 , 정리하자면

우리가 지연초기화 값을 쓰는 이유는

 

- 저사양으로 제한되어 있는 환경에서 메모리를 더욱 효율적으로 사용하거나,

- 클래스를 설계할 때 초기의 값을 정하기 난처해서 나중에 대입하기 위해서 사용한다.

 

를 기억해두자.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형