Light Blue Pointer
본문 바로가기
Developing/TIL(Develop)

Java에서 동일성과 동등성의 차이

by Greedy 2024. 5. 15.

동일성(Identity)

동일성은 두 객체가 동일한 메모리 위치를 참조하는지 여부

두 객체의 참조가 같은 객체를 가리키고 있는지를 확인하는 것

== 연산자를 사용하여 동일성을 비교한다

  • Primitive 타입은 == 연산자를 사용했을 때 값이 같으면 true를 리턴
  • 객체는 == 연산자를 사용했을 때 동일한 메모리 위치가 있으면 true를 리턴

동등성(Equality)

두 객체가 논리적으로 동일한 값을 가지는지

두 객체의 내용이 같은지

equals() 메서드를 사용하여 동등성을 비교

기본적으로 Object 클래스의 equals() 메서드는 ==와 동일하게 동작하지만, 이를 재정의(overriding)하여 객체의 논리적 동등성을 비교할 수 있다

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

// 동등성 비교
if (str1.equals(str2)) {
    System.out.println("str1 and str2 are equal");
} else {
    System.out.println("str1 and str2 are not equal");
}

이 경우, str1str2는 같은 문자열 값을 가지므로 동등성 비교에서는 true를 반환

주요 차이점

  • 기준:
    • 동일성은 객체의 참조(메모리 주소)가 같은지를 확인합니다.
    • 동등성은 객체의 내용(값)이 같은지를 확인합니다.
  • 사용되는 연산자/메서드:
    • 동일성 비교에는 == 연산자를 사용합니다.
    • 동등성 비교에는 equals() 메서드를 사용합니다.
  • 적용 대상:
    • 동일성은 객체의 참조 자체를 비교할 때 사용됩니다.
    • 동등성은 객체의 논리적 상태나 값을 비교할 때 사용됩니다.

hashCode() 메서드

객체끼리 비교할 때에는 Java의 Object 클래스에서 정의된 equals()hashCode() 메서드를 둘 다 재정의해 줘야 한다.

Java에서 hashCode() 메서드는 객체의 해시 코드를 반환하는 데 사용된다.

해시 코드는 정수 값으로, 해시 기반의 컬렉션(예: HashMap, HashSet)에서 객체를 빠르게 검색하고 저장하는 데 사용된다.

equals() 메서드와 hashCode() 메서드는 밀접한 관계가 있으며, 올바르게 동작하도록 함께 재정의해야 한다.

hashCode() 메서드의 역할

hashCode() 메서드는 객체의 해시 코드를 반환하며, 이는 객체의 메모리 주소를 기반으로 한 정수 값이다. 이 값은 객체를 해시 테이블에 저장하고 검색하는 데 사용된다.

equals()hashCode()의 관계

  1. 동등한 객체는 동일한 해시 코드를 가져야 한다
    • equals() 메서드에 의해 두 객체가 같다고 판단되면(a.equals(b) == true), 두 객체의 hashCode() 값은 동일해야 합니다 (a.hashCode() == b.hashCode()).
  2. 동일한 해시 코드를 가지는 객체가 반드시 동등하지는 않다
    • 두 객체의 hashCode() 값이 같다고 해서 반드시 equals() 메서드가 true를 반환하는 것은 아니다.
    • 해시 코드는 대체로 고유한 편이지만 충돌이 발생할 수 있다

hashCode()를 재정의해야 하는가?

hashCode() 메서드를 재정의하지 않으면, Object 클래스의 기본 구현이 사용된다.

기본 구현은 객체의 메모리 주소를 기반으로 해시 코드를 생성하므로, 동등한 두 객체(equals()true를 반환하는 객체)의 해시 코드가 다를 수 있다.

따라서 해시 기반 컬렉션에서 올바르게 동작하지 않게 된다

hashCode() 메서드 재정의

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public static void main(String[] args) {
        Person p1 = new Person("Alice", 30);
        Person p2 = new Person("Alice", 30);

        // 동일성 비교
        if (p1 == p2) {
            System.out.println("p1 and p2 are identical");
        } else {
            System.out.println("p1 and p2 are not identical");
        }

        // 동등성 비교
        if (p1.equals(p2)) {
            System.out.println("p1 and p2 are equal");
        } else {
            System.out.println("p1 and p2 are not equal");
        }

        // 해시 코드 비교
        System.out.println("p1.hashCode(): " + p1.hashCode());
        System.out.println("p2.hashCode(): " + p2.hashCode());
    }
}