BuNa_
IT Story
BuNa_
전체 방문자
오늘
어제
  • 분류 전체보기 (117)
    • CS (14)
      • 운영체제 (8)
      • 네트워크 (0)
      • Design Pattern (1)
      • OOP (4)
    • 대외활동 (24)
      • 우아한테크코스 (14)
      • DND 동아리 (4)
      • UMC 동아리 (5)
      • 해커톤 (1)
    • Android (29)
      • MVVM (2)
      • 스터디 (11)
      • Compose (3)
      • Unit Test (1)
    • Project (5)
      • 어따세워 (5)
      • DnD 과외 서비스 (0)
    • Programming (11)
      • Kotlin (4)
      • 파이썬 (7)
    • Git (1)
    • 인공지능 (22)
    • 백준 (8)
    • 기타 (3)
      • IntelliJ (1)
      • 일상 (0)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

  • External fragmentation
  • RecyclerView
  • 어따세워
  • 원시값 포장
  • Compose
  • 객체지향 생활체조
  • UMC
  • 인공지능 분류
  • Ai
  • 파이썬
  • Android
  • 안드로이드
  • 외부 단편화
  • 다이나믹 프로그래밍
  • 선형회귀
  • 컴공선배
  • 우아한테크코스
  • 우테코 프리코스
  • Baekjoon
  • 운영체제
  • 인공지능
  • K-means
  • 딥러닝
  • 우테코 5기
  • 셀레니움
  • 백준
  • ViewModel
  • MVVM
  • 우테코
  • k-means++

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
BuNa_

IT Story

[Kotlin] val a: Int = 1000과 val b: Int = 1000은 다르다
Programming/Kotlin

[Kotlin] val a: Int = 1000과 val b: Int = 1000은 다르다

2023. 2. 20. 11:30

(우아한테크코스 미션 피드백을 듣다가 한 가지 새로운 사실을 알게 되어 정리합니다.)

 

Kotlin은 정수를 나타내는 타입으로 Int와 Integer가 있습니다.

이 둘의 차이는 Int는 primitive type이지만 Integer는 reference type이라는 점입니다.

이 둘의 존재로 인해, 동등성과 동일성을 비교해야 하는 상황에서 어떠한 차이가 발생하는지 알아보겠습니다.

 

isEqualTo() 메서드는 동등성을 비교합니다. (객체의 내용이 같음)
isSameAs() 메서드는 동일성을 비교합니다. (메모리 주소가 같음)

 

@Test
fun test1() {
    val actual: Int = 1
    val expected: Int = 1
    assertThat(actual).isEqualTo(expected)
    assertThat(actual).isSameAs(expected)
}

해당 테스트 코드를 실행하면 통과할 것입니다.

왜냐하면 Int는 primitive type이므로 동일성, 동등성을 비교해도 같기 때문입니다.

 

 

@Test
fun test2() {
    val actual: Int = 1000
    val expected: Int = 1000
    assertThat(actual).isEqualTo(expected)
    assertThat(actual).isSameAs(expected)
}

그렇다면 이 테스트 코드는 통과할까요?

test1과 숫자만 달라졌기 때문에 통과할 것이라고 생각이 듭니다.

 

 

하지만, 결과를 확인해보니 예상과 달리 테스트 코드는 실패합니다.

test1과 동일하게 primitive type을 비교한 것인데 왜 해당 테스트 코드는 실패하는 것일까요?

그 이유를 알아보기 위해, Kotlin 코드를 Java 코드로 Decompile 해보겠습니다.

 

 

'test2()를 Kotlin에서 Java로 디컴파일한 결과'

Decompile 결과 int 타입을 Integer 타입으로 변환하여 인자를 전달하고 있습니다.

그 이유는 isSameAs() 메서드는 인자로 Object(원시값이 아닌 객체)를 받기 때문입니다.

그래서 JVM은 컴파일 타임에 Int를 Integer.valueOf() 메서드를 통해 Integer로 변환합니다.

 

그럼 여기서 드는 의문은 1이나 1000이나 Integer로 변환하고 나면 reference type이니 결국 서로 다른 메모리(heap) 공간에 할당되어 있을 텐데, 왜 1은 통과하고 1000은 실패하는 것일까요?

 

 

그 이유는 valueOf() 메서드의 특징때문입니다.

위에 조그맣게 작성되어 있는 설명을 읽어보니 valueOf() 메서드는 -128에서 127 범위의 정수는 캐시를 통해 항상 같은 객체를 반환한다고 합니다.

그렇기 때문에 1은 Integer.valueOf()로 전달했을 때 같은 객체를 반환받았기에, 동일성 비교에서 통과할 수 있었던 것입니다.

반면, 1000은 캐시 해놓은 범위를 넘어서기 때문에, 매번 새로운 객체를 만들어 동일성 비교에서 실패할 수밖에 없습니다.

Integer 클래스는 객체를 생성하기도 하고, 관리하는 '객체의 능동적인 관리자' 역할도 함을 알 수 있습니다.

 

 

@Test
fun test3() {
    val actual: Int = 1000
    val expected: Int = 1000
    assertThat(actual == expected).isTrue
    assertThat(actual === expected).isTrue
}

이 테스트 코드는 Kotlin을 조금 공부해 봤다면, 통과할 것이라고 예상할 수 있습니다.

== 연산자는 동등성을 비교하고, === 연산자는 동일성을 비교합니다.

여기에서는 따로 isSameAs()와 같은 메서드를 호출하지 않기 때문에 primitive type 그대로 비교하여, actual과 expected는 동일하다고 할 수 있습니다.

 

 

@Test
fun test4() {
    val actual: Int? = 1
    val expected: Int? = 1
    assertThat(actual == expected).isTrue
    assertThat(actual === expected).isTrue
}

Kotlin에는 타입 뒤에 '?'를 붙여줌으로써 nullable 하게 선언할 수 있습니다.

그럼 nullable 한 타입에 대해서는 동일성 비교에서 어떠한 결과를 보여줄지 생각해 볼 필요가 있습니다.

위 코드는 값이 1인 Int? 타입에 대해 동등성, 동일성 비교를 하고 있습니다.

 

 

test4를 Java 코드로 변환해 보니, Int? 타입이 Integer로 변환되어 있음을 확인할 수 있습니다.

위에서 살펴봤듯이, Integer는 -128부터 127까지는 같은 객체를 공유하기 때문에 동등성, 동일성 테스트에서 모두 True를 반환합니다.

'===' 연산자 대신 isSameAs() 메서드를 사용해도 동일한 결과가 도출됩니다.

 

 

@Test
fun test5() {
    val actual: Int? = 1000
    val expected: Int? = 1000
    assertThat(actual == expected).isTrue
    assertThat(actual === expected).isFalse
}

위 글을 모두 이해했다면, 이 테스트 코드 또한 바로 이해할 수 있을 것입니다.

캐싱 범위(-128에서 127)를 넘어선 값이기 때문에 객체를 새롭게 생성하여, actual과 expected는 서로 다른 객체라고 할 수 있습니다.

따라서 동일성 비교 연산자인 '==='에서 False를 반환합니다.

 

 

Kotlin은 Java에 비해 훨씬 간결하고 편리하다는 특징을 가지고 있지만, 한 단계 더 깊이 알아야 한다는 점을 알 수 있었습니다.

 

해당 포스팅 내용에 오류가 있다면 댓글로 남겨주세요 :)

 

github : https://github.com/tmdgh1592

 

tmdgh1592 - Overview

느리더라도 천천히..!! 😁. tmdgh1592 has 21 repositories available. Follow their code on GitHub.

github.com

 

저작자표시 비영리 변경금지 (새창열림)

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

[Kotlin] Jvm Prefix Annotation 5가지 파헤치기  (1) 2023.04.05
[Kotlin] Value Class (inline class deprecated)  (2) 2023.02.21
[Kotlin] const val vs val - 둘의 차이점은 무엇일까?  (0) 2023.02.11
    'Programming/Kotlin' 카테고리의 다른 글
    • [Kotlin] Jvm Prefix Annotation 5가지 파헤치기
    • [Kotlin] Value Class (inline class deprecated)
    • [Kotlin] const val vs val - 둘의 차이점은 무엇일까?
    BuNa_
    BuNa_
    안드로이드 개발자를 향해 달리고 있는 공대생입니다! 🧑 Android, Kotlin, Java, Python 등 학습하고 있는 내용과 프로젝트를 주로 업로드하고 있습니다. 지적과 조언은 언제나 환영입니다!😊 github : https://github.com/tmdgh1592

    티스토리툴바