CS/Study

[CS] Kotlin과 Java의 동일성, 동등성

bona.com 2025. 5. 21. 11:57

이번에는 객체 공부를 할 때 쉽게 헷갈릴 수 있는 동일성동등성에 대해 공부해 보았다. 또한 Kotlin과 Java에서는 어떻게 다르게 쓰이는 지도 정리했다.

우선, 이름부터 헷갈리기 쉬운 동일성과 동등성의 개념에 대해 알아보자.

 

동일성

Identity, 영어로 하면 이해기 쉽다. 객체의 메모리  주소값이 같은지 식별한다.

즉, 내용이 같더라도 주소가 다르다면 다른 객체로 판단하는 것이다.

 

동등성

Equality, 논리적으로 같은 지위를 지녔는지 확인하는 것이다.

즉, 변수가 참조하고 있는 객체의 주소가 서로 다르더라도 내용만 같으면 두 변수는 동등하다고 본다.

 

Java의 동일성, 동등성

그럼 Java에서는 동일성과 동등성이 어떻게 판단되는지 알아보자.

String str1 = new String("Bona");
String str2 = new String("Bona");

System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // true
  • 동일성은 == 연산을 통해 확인한다.
    • 위 코드에서 new를 통해 다른 String 객체를 메모리에 할당하였으므로 str1과 str2의 주솟값은 달라서 false
  • 동등성은 equals 연산을 통해 확인한다.
    • 위 코드에서 두 객체의 내용이 같기 때문에 true

 

여기서 주의해야 할 점은 equals 연산자로 항상 동등성을 판단할 수 있는 것은 아니다.

public class Main {
    public static void main(String[] args) {

        Student student1 = new Student("Bona");
        Student student2 = new Student("Bona");

        System.out.println(student1 == student2); // false
        System.out.println(student1.equals(student2)); // false

    }

    public static class Student {
        private final String name;

        public Student(String name) {
            this.name = name;
        }
    }
}

Object 객체로 비교를 하게 된다면 == 연산과 equals 연산 모두 false가 뜨는 것을 확인할 수 있다.

왜 이런 결과가 나오게 되는 것일까?🤔

 

그 이유는 eqauls가 아래처럼 정의되어 있기 때문이다.

public boolean equals(Object obj) {
    return (this == obj);
}

Object 객체에서 정의하고 있는 equals는 단순히 == 연산을 통해 동일성 검사만 하고 있는 것을 확인할 수 있다.

 

그렇다면 제일 처음에 본 String의 equals는 어떠할까?🤔

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    return (anObject instanceof String aString)
            && (!COMPACT_STRINGS || this.coder == aString.coder)
            && StringLatin1.equals(value, aString.value);
}

먼저 동일성 검사를 수행한 다음, 인자로 들어온 anObject가 String이라면 aString 변수로 캐스팅 되어 동등성 검사를 수행하고 있다.

 

해당 함수의 공식 문서를 해석하면 아래와 같은데 참고만 해 주면 된다.

Compares this string to the specified object. (이 문자열을 지정된 객체와 비교합니다.)
The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object. (그 결과는 인자가 null이 아니고, 이 문자열과 동일한 문자 시퀀스를 나타내는 String 객체일 경우에만 true 입니다.)

 

따라서 Object 타입일 때도 equals 메소드를 통해 동등성 검사를 하고 싶다면 이를 오버라이드 해 주면 된다!!

@Override
public boolean equals(Object o) {
    if (this == o) // 1번
        return true;
    if (o == null || getClass() != o.getClass()) // 2번
        return false;
    Student student = (Student)o; // 3번
    return name.equals(student.name);
}
  1. 동일성 검사를 통해 주소가 같은지 먼저 확인
  2. null이 거나 다른 자료형인지 확인
  3. 그 후 name 필드 값이 동일한지 확인 (이때 쓰이는 equals 메소드는 위에서 본 String의 equals과 동일)
System.out.println(student1.equals(student2)); // true

 

그러면 위에서 false가 나왔던 equals 연산은 true가 된다.

 

Kotlin의 동일성, 동등성

이제 kotlin 코드에서는 어떻게 동일성과 동등성을 검사하는지 알아보자.

class Student(
    val name: String,
)

val student1 = Student("Bona")
val student2 = Student("Bona")

fun main() {
    println(student1 == student2) // false
}
  • 동일성은 === 연산을 통해 확인한다.
  • 동등성은 == 연산을 통해 확인한다.
    • Kotlin의 ==은 내부적으로 equals를 호출해서 객체를 비교한다.
    • 따라서 위 코드에서는 내부적으로 equals를 호출하고, 별도의 equlas 함수를 오버라이드 하지 않았기 때문에 동일성 비교를 하게 된 것이다.
    • 동일성 비교 → 주소가 다르기 때문에 결과는 false

 

따라서 동등성 비교를 하기 위해서는 Kotlin도 equals 함수를 오버라이드 해 주면 결과가 true로 나온다.

class Student(
    val name: String,
) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true // 1번
        if (other !is Student) return false // 2번
        return name == other.name // 3번
    }

    override fun hashCode(): Int {
        return name.hashCode()
    }
}

val student1 = Student("Bona")
val student2 = Student("Bona")

fun main() {
    println(student1 == student2) // true
}
  1. 동일성 검사(===연산)를 통해 주소가 같은지 먼저 확인
  2. 다른 자료형인지 확인
  3. 그 후 name 필드 값이 동일한지 확인

 

단, Kotlin에서는 data class를 쓰면 equals, hashCode, toString 등이 자동 구현되므로 위 Student 클래스는 아래처럼 더 간단하게 쓸 수도 있다.

data class Student(val name: String)

 

References

https://steady-coding.tistory.com/534

https://creampuffy.tistory.com/140

https://velog.io/@conatuseus/Java%EC%99%80-Kotlin%EC%9D%98-%EB%8F%99%EB%93%B1%EC%84%B1%EA%B3%BC-%EB%8F%99%EC%9D%BC%EC%84%B1