코틀린의 Eqaulity는 크게 두가지가 존재한다.
Structual Equality : 동등성 (자바의 재정의한 equals
)
Referential Equality : 동일성 (자바의 ==
)
그렇다면 코틀린과 자바를 비교해보자.
JVM에서 100%호환이 가능한 Kotlin은 Java와 어떻게 차이가 있을까?
Java에서는 내용을 비교할 때, equals
로 객체의 참조 값이 아니라, 내용을 비교할 수 있다는 것을 알고 있다.
사실 엄밀히 말하면 이 말은 틀린 말이다.
Object클래스의 equals는 아래 사진과 같이 정의되어 있다.
즉, 이 말인 즉슨 ==
을 통해 객체의 주소값을 비교하고 있다는 뜻이다.
하지만, 우리가 알고있는 대표적인 클래스들은 이러한 equals 메서드를 '주소값'이 동일한 경우뿐만 아니라, '내용'도 동일한지 여부를 확인한다. 이 때문에 우리가, equals
메서드가 내용을 비교하는 메서드라고 착각하기 쉽다. 따라서 equals
함수를 재정의했기 때문에 내용을 비교할 수 있다고 바로 알자.
예시 코드
public static void main(String[] args) { class Pos{ int x; Pos(int x ){ this.x = x; } } Pos p1 = new Pos(1); Pos p2 = new Pos(1); System.out.println(p1.equals(p2)); //false }
위의 예시에서 true로 만들기 위해서는 equals메서드를 재정의 해야한다.
결국 equals
메서드는 객체의 내용(Structual Eqaulity)를 따지기 위해 존재하는 것이고,==
은 객체의 주소값(Referential Equality)를 따지기 위해 존재한다.
Java의 객체 내용값을 비교하기 위해 재정의한 equals
메서드와 동일한 역할을 Kotlin에서는 ==
을 통해 담당한다.
class TestClass(val value: Int) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is TestClass) return false
return value == other.value
}
}
fun test() {
var a: TestClass = TestClass(10000)
var b: TestClass? = TestClass(10000)
println("a === b: ${a === b}") // false
println("a == b: ${a == b}") // true
}
fun main() {
test()
}
위 코드의 Byte코드를 통해 Java로 변환하면
public static final void test() {
TestClass a = new TestClass(10000);
TestClass b = new TestClass(10000);
String var2 = "a === b: " + (a == b);
System.out.println(var2);
var2 = "a == b: " + Intrinsics.areEqual(a, b);
System.out.println(var2);
}
처럼 변한다.
이를 통해 Kotlin의 ===
은 Java의 ==
과 동일하고,
Kotlin의 ==
은 Java의 equals
와 동일하다는 것을 알 수 있다.