동등성과 동일성에 대한 개념은 프로그래밍 언어를 배울 때 반드시 이해하고 넘어가야 하는 것 중 하나다. 여기에는 코틀린에서 동등성과 동일성이 어떻게 다뤄지는지 간단히 정리해보았다.
다음의 코틀린 공식문서를 많이 참고해보았다.
https://kotlinlang.org/docs/equality.html
Equality | Kotlin
kotlinlang.org
1. 동등성과 동일성
Kotlin에서는 두 객체를 비교할 때 두 가지 타입이 존재한다. 바로 동등성(Structure Equality)과 동일성(Referential Equality)이다.
먼저 둘의 차이는 다음과 같다.
동등성은 두 객체를 equals() 메서드로 비교한다. ==
으로 값을 비교한다.
동일성은 두 변수가 참조하는 주소가 같은지 비교한다. 다시 말해 어떤 두 객체가 메모리상에서 같은 위치에 있는 완전히 같은 인스턴스일 때만 동등하다고 한다. ===
을 사용하여 참조가 동일한지 확인할 수 있다.
1-1. 동등성
두 객체가 동등한지를 비교하려면 ==
연산자를 이용하면 된다. 만약 두 객체가 동등하지 않은지를 알기위해서는 !=
을 이용할 수 있다.
fun main() {
val a = "메롱"
val b = "메롱"
println(a == b) // true
// 두 객체의 값이 같기 때문에 동일하다
println(a != b) // false
// 두 객체가 동일하지 않냐고 물었기 때문에 false가 나온다
}
관습에 따라 a == b는 다음과 같이 변환될 수 있다.
a?.equals(b) ?: (b === null)
a가 null이 아니라면 'equals()' 함수를 호출하게 된다. 만약 a가 null이라면 엘비스 연산자에 따라 b가 null인지( b === null ) 동일성을 확인하게 된다. 아래와 같이 코드를 작성해 확인해 볼 수 있다.
fun main() {
val a = "메롱"
val b = null
val c = null
val d = c
println(a == b) // false
println(b == d) // true
}
null과 명시적으로 비교할 때 ' == null '은 자동적으로 ' === null '로 변환되기 때문에 코드를 그에 맞춰 변경할 필요가 없다고 하니 참고해두면 좋을 것 같다.
1-2. 동일성
두 객체가 동일한지 비교하려면 ===
연산자를 이용하면 된다. 두 객체가 동일하지 않은지 비교하려면 !==
연산자를 이용하면 된다.
아래에는 문자열에서의 동등성과 동일성 비교를 하는 코드를 작성해보았다.
fun main() {
val str1 = "Hello"
val str2 = String(StringBuilder("Hello"))
val str3 = String(charArrayOf('H','e','l','l','o'))
println(str1 == str2) // true
println(str1 == str3) // true
println(str2 == str3) // true
// 문자열이 모두 동등하기 때문에 true가 나온다
println(str1 === str2) // false
println(str1 === str3) // false
println(str2 === str3) // false
// 문자열의 주소값이 모두 다르기 때문에 false
}
런타임시의 원시 타입으로 표현되는 값(대표적인 예로 Int)의 경우는 ===
으로 검사를 하는 것이 ==
으로 검사하는 것과 동일하게 된다.
fun main() {
val a = 100
val b = 100
println(a == b) // true
println(a === b) // true
// 런타임시 원시 타입 값을 가지기 때문에 == 과 같다
}
간단한 data class를 만들고 객체의 동등성과 동일성을 비교해보았다. data class는 자동적으로 equals(), toString(), hashCode()같은 메서드들을 만들어주기 때문에 equals()를 오버라이드 하지 않아도 동등성 비교를 할 수 있다.
fun main() {
val obj1 = TwoInt(10,20)
val obj2 = obj1
val obj3 = TwoInt(10,20)
println(obj1 === obj2) // true
// 둘은 같은 주소값을 가지기 때문에 동일하다
println(obj1 == obj3) // true
println(obj1 === obj3) // false
// obj1과 obj3은 동등하지만 동일하지 않다
println(obj1 !== obj3) // true
// === 대신 !==을 사용하면 반대의 결과가 나온다
}
data class TwoInt (val a:Int, val b:Int)
'Kotlin' 카테고리의 다른 글
Kotlin에서 정규 표현식 사용하기 (2) (0) | 2024.12.24 |
---|---|
Kotlin에서 정규 표현식 사용하기 (1) (0) | 2024.12.20 |
Kotlin의 원시배열과 참조배열 (0) | 2024.12.16 |