Kotlin 공유자료_값비교(==)와 참조비교(===)
Kotlin 공유자료_값비교(==)와 참조비교(===)

Kotlin 공유자료_값비교(==)와 참조비교(===)

1️⃣ 오늘의 Keyword

        2️⃣ 학습 내용 및 예시

        • 아래의 결과를 정확히 설명하고, 결과를 예측할 수 있는가??
        //일반 객체... class User val user1 = User() val user2: User? = User() val user3: User? = user1 println("${user1 == user2}, ${user1 === user2}, ${user1 == user3}, ${user1 === user3}") //false, false, true, true //일반 객체는 non-null, nullable 모두 겍체비교이다. ==, === 모두 객체비교이다 //기초 타입 - non-null val data1 = 1000 val data2 = 1000 println("${data1 == data2}, ${data1 === data2}") //기초 타입의 객체가 non-null 로 선언되면.. 자바로 변형시에 primitive type 으로 변형된다..객체가 아니다 //값을 비교할 수 밖에 없다 //기초 타입 - nullable val data3: Int? = 1000 val data4: Int? = 1000 println("${data3 == data4}, ${data3 === data4}") //true, false //? 로 선언..null 대입 가능. 자바로 변형시에 객체로 변형할 수 밖에 없다. Integer //Int 를 wrapper 클래스인 Integer 로 변형시켜서 Boxing 효과. //값을 비교하고 싶을 경우 (==), 객체를 비교하고 싶은 경우 (===) val data5: Int? = 10 val data6: Int? = 10 println("${data5 == data6}, ${data5 === data6}") //true, true val data7: Int = 100 val data8: Int? = 100 println("${data7 == data8}, ${data7 === data8}") //true, true val data9: Int = 1000 val data10: Int? = 1000 println("${data9 == data10}, ${data9 === data10}") //true, true
         
        • 코틀린에서 ===의 동일성 비교
          • primitive 값은 객체가 아니기 때문에 원래 참조값이 없음
          • 그러면 아래처럼 === 참조비교를 하려고 하면??
            • val data1 = 1000 val data2 = 1000 println("${data1 == data2}, ${data1 === data2}")
          • 둘다 Integer.valueOF(1000)으로 박싱해서 객체 생성후 참조비교해야하지만,
            억지로 둘다 원시타입인 값을 둘다 객체로 만들어서 당연히 각각 다른 주소값을 가질텐데
            꼭 둘다 원시타입의 값인 것을 참조비교 해야겠어? 권장하지 않아.
            그래서 사용이 불가라고 표현.
            ⇒ identity equality for arguments of types ‘Int' and 'Int' is deprecated
          • 왜?? primitive Int는 숫자 4바이트인데,
            boxing하면 Integer 객체를 만들고 힙 할당 부담이 생긴다.
            === 참조비교 한번 할 때마다 객체를 2개씩 만들어서 당연히 false인 값을 드려?
          • 그러니까 그냥 primitive 값끼리 === (참조비교)는 ==의 값비교로 동작하게 정의함.
            ⇒ 쓸데없는 boxing으로 성능저하 / 쓸데없는 항상 false 확인을 피함.
          •  
          • 그렇다면 아래처럼 Int와 Int? 의 비교는?
          • val data5: Int = 1500 val data6: Int? = 1500 println("${data5 == data6}, ${data5 === data6}") //true, true
          • 위와 같은 이유로 주소 값이 없는 원시 타입 값을 주소값과 비교하라고?
            박싱해서 당연히 다른 객체가 생성되는데, 항상 false 인데??
          • 그러니까 Int?를 언박싱해서 그냥 값을 비교해줄게
          • 즉, Kotlin 문서상 “런타임에 primitive로 표현되는 값이면 ===가 ==와 같다”가 공식 규칙
          • 복잡한 구조 속에서 primitive 타입을 잃는 순간, ===로 주소비교
         
        • JVM의 Integer 캐싱 규칙
          • JVM 구현체에 따라 다를 수 있음
          • HotSpot (Oracle, OpenJDK)의 경우
            -128 ~ 127 범위의 Integer 객체를
            JVM 런타임 초기화단계에서 미리 만들어 두고 재사용함
            그 마저도 캐시 범위 설정 옵션이 또 있음
          • 이것이 Kotlin이 말하는 **“unstable”**의 정체
          • 즉, ‘현재의 JVM이 어떤 최적화를 쓰고 있느냐”에 결과를 맡기는게 됨. 그래서
            로컬에선 됐다.
            서버에선 다르게 나왔다.
            이런 경우가 생길 수 있음.
         
        • 사실상 실무 결론
          • 숫자, Boolean, Char → 절대 === 쓰지 마라
          • 객체 identity가 의미 있는 경우만 ===
         
         
         

        ❓ 이해 안 된 부분 / 도움 요청

           

          ‼️오늘 느낀 점