본문 바로가기

Language/Kotlin

[Kotlin] 변수의 고급 기술 (상수, lateinit, lazy)

728x90
반응형

상수

val은 할당된 객체를 바꿀 수 없을 뿐이지 객체 내부의 속성을 변경할 수는 없는 것은 아니다.

그러나 ‘상수’는 절대 변경이 불가능하다. 컴파일 시점에 결정되어 절대 바꿀 수 없다.

const val CONST_A = 1234

 

  • 상수로 선언될 수 있는 값은 기본 자료형만 가능하다.(String 자료형 포함)
  • 상수의 이름을 만들 때는 의례적으로 대문자와 언더바(_)만 사용한다. 이를 통해 변수가 아닌 상수라는 점을 알린다.
  • 런타임에 생성될 수 있는 일반적인 다른 클래스의 객체들은 담을 수 없다.
  • 상수는 클래스의 속성이나 지역 변수 등으로는 사용할 수 없으며, 반드시 companion object 안에 선언하여 객체의 생성과 관계없이 클래스와 관계된 고정적인 값으로만 사용하게 된다.

선언

class Sample{
	companion object{
		const val CONST_A = 1234
	}
}

사용

Sample.CONST_A

 

상수가 자주 사용되는 예

fun main(){
    val foodCourt = FoodCourt()

    foodCourt.searchPrice(FoodCourt.FOOD_CREAM_PASTA)
    foodCourt.searchPrice(FoodCourt.FOOD_STEAK)
    foodCourt.searchPrice(FoodCourt.FOOD_PIZZA)
}

class FoodCourt{
    fun searchPrice(foodName: String){
        val price = when(foodName){
            FOOD_CREAM_PASTA -> 13000
            FOOD_STEAK -> 25000
            FOOD_PIZZA -> 15000
            else -> 0
        }
        println("${foodName}의 가격은 ${price}원 입니다")
    }

    companion object{
        const val FOOD_CREAM_PASTA = "크림파스타"
        const val FOOD_STEAK = "스테이크"
        const val FOOD_PIZZA = "피자"
    }
} 

// 출력 :
// 크림파스타의 가격은 13000원 입니다
// 스테이크의 가격은 25000원 입니다
// 피자의 가격은 15000원 입니다

 

굳이 변수를 사용하지 않고 상수를 별도로 사용하는 이유?

: 변수의 경우 런타임 시 객체를 생성하는데 시간이 더 소요되어 성능의 하락이 있기 때문이다. 따라서 늘 고정적으로 사용할 값은 상수를 통해 객체의 생성없이 메모리에 값을 고정하여 사용함으로써 성능을 향상시킬 수 있다.

 

lateinit (늦은 초기화)

코틀린에서는 변수를 선언할 때 객체를 바로 할당하지 않는 경우에 컴파일이 되지 않는다.

하지만 변수에 객체를 할당하는 것을 선언과 동시에 할 수 없을 때도 있다. 이럴 때는 var 앞에 lateinit을 사용하여 일단 변수만 선언하고 초기값의 할당은 나중에 할 수 있도록 한다.

lateinit var a: Int

 

lateinit var 변수의 제한사항

  • 초기값 할당 전까지 변수를 사용할 수 없다. (에러 발생)
  • 기본 자료형에는 사용할 수 없다. (String 클래스에는 사용 가능)

 

lateinit 변수의 초기화를 하였는지 여부를 확인할 때는

::a.isInitialized

로 초기화가 되었는지 확인하여 사용할 수 있으므로 오류를 막을 수 있다.

 

fun main(){
    val a = LateInitSample()

    println(a.getLateInitText())  // 기본값
    a.text = "새로 할당한 값"
    println(a.getLateInitText())  // 새로 할당한 값
}

class LateInitSample{
    lateinit var text: String

    fun getLateInitText(): String{
        if(::text.isInitialized){
            return text
        } else{
            return "기본값"
        }
    }
}

 

지연 대리자 속성

: 변수를 사용하는 시점까지 초기화를 자동으로 늦춰줌

val a: Int by lazy{ 7 ]

 

코드에서는 선언 시 즉시 객체를 생성 및 할당하여 변수를 초기화하는 형태를 갖고 있지만 실제 실행시에는 변수를 사용하는 시점에 초기화하는 과정을 진행함으로써 코드의 실행시간을 최적화 할 수 있다.

 

람다함수로 초기화가 진행되므로 함수 안에 여러 개의 구문이 들어갈 수 있으며 맨 마지막 구문의 결과가 변수에 할당된다.

val a: Int by lazy{
    println("initializing")
    7    // 이렇게 해도 어차피 값은 7이 됨
}

 

fun main(){
    val number: Int by lazy{
        println("초기화를 합니다")
        7
    }

    println("코드를 시작합니다")
    println(number)
    println(number)
}

// 출력:
// 코드를 시작합니다
// 초기화를 합니다
// 7
// 7

두 번째 number을 출력할 때는 이미 초기화를 했기 때문에 다시 초기화 구문을 실행하지 않음을 알 수 있다.

728x90
반응형

'Language > Kotlin' 카테고리의 다른 글

[Kotlin] 코루틴을 통한 비동기 처리  (0) 2023.09.25
[Kotlin] 비트연산  (0) 2023.09.25
[Kotlin] 컬렉션 함수 (2)  (0) 2023.09.24
[Kotlin] 컬렉션 함수 (1)  (0) 2023.09.22
[Kotlin] 컬렉션(2) Set과 Map  (0) 2023.09.22