Kotlin (코틀린)

[Kotlin] 코틀린의 참조 타입 → 원시 타입 변환 확인 / 기본형 · 참조형 자료형의 비교 원리 / 이중 등호와 삼중 등호 (==, ===

Oscar:) 2024. 5. 19. 18:50

 
 
앞선 코틀린의 자료형을 소개하는 포스팅에서 언급한 내용을 확인하는 포스팅이다.
다소 쓸데없고(?) 딱딱할 수 있지만, 알아두면 좋은 가벼운 내용만을 다룬다.
 
 
주된 내용은 참조 타입으로 사용하는 기존 원시 타입 변수가
실제로 원시 타입으로 변환 처리되는지 확인하는 과정이다.
 
 
 


 

기본형? 참조형?

 
 
기본형과 참조형은 앞선 많은 포스팅들에서 다루었던 내용이다.
궁금하다면 참고하기 바란다.
 

[Kotlin] 코틀린 자료형 / 타입 캐스팅 / 값 비교

이번 포스팅에서는 코틀린의 자료형에 대해 알아보자.   자료형  코틀린에서는 자료형을 원시 타입과 참조 타입으로 구분하지 않는다.모든 자료형은 참조 타입으로 통일되었다.  타입키워

oscarstory.tistory.com

 

[Kotlin] 코틀린 래퍼 클래스 Wrapper Class

지난 포스팅에서 코틀린의 자료형에 대해 다루었고, 코틀린에서는 모든 자료형을 참조 타입으로 통일한다고 언급했었다.  이번 포스팅에서는 원시 타입과 참조 타입,코틀린에서의 래퍼 클래스

oscarstory.tistory.com

 


 
 
이번 포스팅을 위해 간단히 정리해본다.
 

기본형 자료형(Primitive Type)은 흔히 원시 타입이라 불리며
자바에서는 int, double, char, boolean 등이 해당한다.

참조형 자료형(Reference Type)은 흔히 참조 타입이라 불리며
String을 포함한 모든 클래스, 인터페이스에 해당한다.

 
 
하지만 코틀린에서는 기존의 기본형 자료형도 모두 참조형 자료형으로 통합하여 사용된다.
 
그렇기에 int → Int 처럼 사용할 수 있지만,
사실 컴파일 시 코틀린이 다시 기본형 자료형으로 자동 변환해주는 것이다.
 
 
그리고 이제...! 그 내용을 확인해본다.
 
 
 


이중 등호(==), 삼중 등호(===)

 
 
위에서 설명한 내용을 확인하려면, 이중 등호와 삼중 등호에 대한 개념이 필요하다.
 
이중 등호 (==) : 단순히 값만을 비교한다.
● 삼중 등호 (===) : 메모리 내 힙 영역에 저장되어 있는 데이터의 참조 주소를 비교한다.
 
 
 

🟢 예제를 통해 확인해보자.

// 간단한 데이터 클래스 생성
data class Student(
    val name: String,
    val age: Int
)


// 객체 비교 후 출력
fun main() {
    val studentA = Student("Oscar", 29)
    val studentB = Student("Oscar", 29)

    println(studentA == studentB)
    println(studentA === studentB)
}

 
2개의 Student 클래스에 동일한 값을 넣고 비교해 보았다.
 

 
두 객체의 값은 동일하기에 이중 등호 출력문은 true.
하지만 두 객체의 참조 주소값은 다르기에 false를 출력한 모습이다.
 
 
위 내용의 메모리 구조를 간단히 떠올린다면 다음과 같다.
 

 
참조 타입 자료형은 모두 위와 같은 구조를 가진다.
 
 


 
 

🟢 그렇다면 이제 기존의 원시 타입 자료형이 정말
참조 타입 → 원시 타입 변환 처리가 되는지 확인해보자.

val a: Int = 128
val b: Int = 128

println(a == b)
println(a === b)

 
 
Int 자료형 변수를 초기화하고 이중 등호와 삼중 등호로 비교하여 출력해 보았다.
 

 
2개의 결과 모두 true를 출력한 모습이다.
 
Int 자료형이 정말 참조 타입으로 적용되었다면 실제 값은 Heap 영역에 저장되었을 것이고,
삼중 등호를 사용했을 때 false를 출력했을 것이다.
 
Int 녀석...
참조 타입인 척하지만 사실 원시 타입으로 컴파일된다는 것을 확인할 수 있었다.
 
 
 


기타 ☆★

 
 

✅ null 허용한 자료형이라면?

 
이 부분도 정말 중요하다.

val a: Int? = 128
val b: Int? = 128

println(a == b)
println(a === b)

 
두 변수 a, b는 동일한 타입과 동일한 값을 가진다.
 
하지만 코틀린에서 null을 허용하는 자료형은 진짜 참조 타입으로 취급된다.
해당 자료형은 컴파일될 때에도 원시 타입으로 변환되지 않는다.
 
 
따라서 단순 Int 값 비교와는 다른 결과를 출력한다.
 

 
원시 타입으로 취급되지 않았기에, 참조 주소가 다르다는 결과를 확인할 수 있다.
 
 
따라서 위 예제도 Heap 메모리에 2개의 주소값을 가진 영역을 차지했다고 볼 수 있다.
 

 
 
 


 
 

✅ 위 예제들에서 Int 값을 128로 테스트한 이유

 
기존대로라면 원시 타입 변수의 값은 스택에 저장되는 것이 맞지만,
코틀린에서는 참조형으로 선언한 변수의 값이
byte의 범위(-128~127)에 포함된다면 값을 캐시에 저장하는 특성이 있다.
 
작은 범위의 값은 프로그램에서 자주 사용되지만 용량이 작기 때문에
더 좋은 성능의 프로그램을 위해 위와 같이 적용된다.
 
이러한 이유로 위 예제에서는 128 이상의 값으로 테스트했으니
byte의 범위 값으로 테스트하고 놀라는 사람은 없었으면 좋겠다..!
 
 
 


정리

 
 
● 실제 값을 비교할 때는 이중 등호(==), 참조 주소를 비교할 때는 삼중 등호(===)를 사용한다.
 
● 코틀린에서는 기존 원시 타입을 참조 타입처럼 사용할 수 있지만,
사실 컴파일 할 때 원시 타입으로 자동 변환 처리된다.
 
● 하지만 기존 원시 타입 자료형에 ? 키워드로 null을 허용한다면 진짜 참조 타입으로 취급된다.
 
● byte 자료형의 범위 내 값을 다룰 때는 스택 메모리가 아닌 캐시에 저장하는 방식을 사용한다.
 
 
 


 
 
 
 
단순한 자료형을 비교한 포스팅이었지만, 뭔가 쉬운 듯 어려운 느낌이다.