Kotlin/Variable and Function

Kotlin의 val은 왜 엄밀한 의미의 불변 변수가 아닌가?

Dev.Cho 2021. 10. 2. 23:50

Kotlin에서는 var을 읽기와 쓰기가 모두 가능한 가변 변수로 val을 읽기만 가능하면 불변 변수로 정의한다. 하지만, 실제로는 var은 물론 val 또한 엄밀한 의미의 불변이 아니다. 지금부터 이유를 알아보도록 하자.

 

변수에 값을 할당하는 것은 정확히 말하면 메모리 공간을 할당하는 것이다. 다음의 코드를 예시로 들어보자.

val blogName = "Kotlin World"
var date = "2021-10-02"

위의 코드를 실행하면 blogName이라는 변수값이 정해지고 해당 변수값을 참조했을 때 "Kotlin World"가 저장된 메모리 공간을 반환한다. date라는 변수값은 "2021-10-02"가 저장된 메모리 공간을 반환한다.

 

var date = "2021-10-02"
date = "2021-10-03"

만약 date 값이 위와 같이 "2021-10-03"으로 바뀌면 "2021-10-02"는 곧바로 지워지는 것이 아니며, "2021-10-03"이 메모리 공간에 새로 생성되고 date가 가리키는 메모리 공간은 "2021-10-03"의 주소값으로 바뀐다. 즉, "2021-10-02"는 메모리 공간 상에 자신을 참조하는 변수가 없는 채로 있는다.

 

일정 시간 후에 가비지 컬렉터(Garbage Collector)라 불리는 JVM의 구성요소는 가리키는 변수가 없는 "2021-10-02"를 메모리 상에서 지운다. 새로운 메모리 공간의 할당이 어떤 의미인지 알았으면 다시 원 주제로 돌아가보자.

 

만약 메모리 공간의 변경이 없는 채로 값을 바꿀 수 있다면?

만약 메모리 공간이 변경이 안된채로 값이 변경될 수 있다면 어떻게 될까? 원시타입(Primitive Type)의 변수나 String 은 메모리 공간의 변경이 되지 않은 채로 값의 변경을 지원을 하지 않지만,  컬렉션이라 불리는 List나 Array등의 자료 구조는 메모리 공간이 변경이 되지 않은 채로 값의 변경을 지원한다.

 

간단하게 Array를 val로 선언한 후 내부를 변경해보자.

fun main() {
    val array = arrayOf<Int>(1, 2, 3)
    array[0] = 3
    println("array[0]: ${array[0]}")
    println("array[1]: ${array[1]}")
    println("array[2]: ${array[2]}")
}

위의 값의 출력은 다음과 같이 나온다.

분명히 array를 val 로 선언하고 0번 공간에 1을 할당했는데 3이 나온 것을 볼 수 있다. 즉, 불변 변수라고 하더라도 메모리 공간을 재할당하지 않고 내부의 값을 변경할 수 있는 함수가 있다면, 엄밀한 의미의 불변이 아니게 된다.

 

정리하면 다음과 같다.

val 로 선언하더라도 메모리 공간을 재할당하지 않고 내부의 값을 변경할 수 있는 함수가 있다면, 엄밀한 의미의 불변이 아니게 된다.

 

반응형