ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kotlin] 동등성 비교와 동일성 비교 그리고 캐시 조회
    legacy/Kotlin 2023. 9. 19. 09:21

     

    코틀린에서 "=="와 "===" 연산자를 제공합니다. "=="은 동등성 비교(값 비교)를 제공하고 "==="은 동일성 비교(참조값 비교)를 제공합니다. 얼핏 보면 쉬운 내용이면서도 헷갈리는 부분이 존재합니다. "=="와 "==="의 차이점 그리고 캐시로부터 값을 가져오는 상황을 이해해봅시다.


    동등성(==) 비교

    ==는 동등성 비교를 제공합니다.

     

    아래에 num1 변수가 존재합니다. 코틀린의 특성상 참조형 변수로 선언되었지만, 컴파일 시에 참조형 -> 기본형으로 변경되어 저장됩니다. 즉 주소값을 저장하는 것이 아니라 값 그 자체를 저장하게 됩니다.(힙에 저장되는 것이 아닌 스택에 저장됨) 따라서 num1과 num2의 동일성 비교에서 true를 반환합니다.

    fun main() {
        var num1: Int = 10
        var num2: Int = 10
    
        println("num1 == num2 : ${num1 == num2}")
    }

    아래는 null을 허용한 변수 num3과 num4입니다. num3와 num4는 값이 저장되는 것이 아니라 주소값이 저장합니다. 즉 스택에 저장된 값을 저장하는 것이 아니라 힙에 저장된 주소값을 참조하고 있습니다. 동일성 비교는 값을 비교하는 것이기 때문에 num3와 num4의 동일성 비교에서 true를 반환합니다.

    fun main() {
        var num1: Int = 10
    
        var num3: Int? = num1
        var num4: Int? = num1
        println("num3 == num4 : ${num3 == num4}")
    }

    동일성(===) 비교

    ===는 동일성 비교를 제공합니다.

     

    아래 코드는 동등성 비교에서 사용된 코드와 동일합니다. 위에서 말했듯이 코틀린은 컴파일 과정에서 참조형 -> 기본형으로 변경하여 저장합니다. 따라서 동일성 비교를 하더라도 스택에 저장된 값을 비교하게 되므로 true를 반환합니다.

    fun main() {
        var num1: Int = 10
        var num2: Int = 10
    
        println("num1 === num2 : ${num1 === num2}")
    }

     

    아래는 null을 허용한 변수 num3과 num4입니다. 즉 스택에 저장된 값을 저장하지 않고 힙에 저장된 값을 참조합니다. 따라서 주소값을 가지고 있기 때문에 동일성 비교에서 false를 반환해야 합니다.

    fun main() {
        var num1: Int = 10
        var num3: Int? = num1
        var num4: Int? = num1
    
        println("num3 === num4 : ${num3 === num4}")
    }

    그런데 true를 반환합니다. 다른 참조값을 가지는 num3와 num4를 비교했는데 어째서 true를 반환하는 것일까요?

    정답은 캐시에 저장된 값을 참조하기 때문입니다. 코틀린은 -128 ~ 127 사이의 값은 캐시에 저장하여 사용합니다. 더 좋은 성능의 프로그램을 만들 수 있기 때문이라고 합니다. 

    num1은 10을 저장하고 있기 때문에 캐시에 저장되어 있습니다. num3와 num4는 캐시에 저장된 값을 참조하므로 같은 주소값을 가집니다. 따라서 true를 반환하게 됩니다.

     

    num1에 128을 저장하면 캐시가 아닌 스택에 저장됩니다. 따라서 num3와 num4는 캐시의 주소값을 참조하는 것이 아니라 힙에 저장된 주소값을 참조합니다. 따라서 num3 === num4는 false를 반환하게 됩니다.

    fun main() {
        var num1: Int = 128
        var num3: Int? = num1
        var num4: Int? = num1
    
        println("num3 === num4 : ${num3 === num4}")
    }


    결론

    -128 ~ 127의 값은 스택이 아닌 캐시에 저장된다. 사이의 값을 갖는 변수, null을 허용하는 변수 둘 다 동일성 비교 시에 true를 반환한다.

Designed by Tistory.