GitHub

https://github.com/Choidongjun0830

공부

equals()와 hashCode()의 개념과 관계

gogi masidda 2025. 3. 1. 19:36

equals() 메서드

equals() 메서드는 두 객체가 논리적으로 동일한지를 비교하기 위해 사용된다. 기본적으로 Object 클래스의 equals() 메서드는 두 객체의 참조(메모리 주소)가 동일한지를 비교하며, 따라서 == 연산자와 동일한 동작을 한다.

그러나, equals() 메서드를 오버라이딩하면 객체의 특정 필드 값을 비교하여 논리적으로 동일한지를 정의할 수 있다.

equals() 기본 동작

class Person {
    private String name;
    
    public Person(String name) {
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");
        
        System.out.println(p1.equals(p2)); // false (Object의 기본 equals() 사용)
    }
}

위 예제에서 equals() 메서드를 오버라이딩하지 않으면 두 객체의 메모리 주소가 다르므로 false가 출력된다.

equals() 오버라이딩 예제

class Person {
    private String name;
    
    public Person(String name) {
        this.name = name;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        Person person = (Person) obj;
        return name.equals(person.name);
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");
        
        System.out.println(p1.equals(p2)); // true
    }
}

위처럼 equals()를 오버라이딩하면 논리적으로 동일한 객체로 간주할 수 있다.


hashCode() 메서드

hashCode()는 객체를 식별하는 해시 값을 반환하는 메서드이다. Object의 기본 hashCode()는 객체의 메모리 주소를 기반으로 생성된 정수 값을 반환한다.

컬렉션 프레임워크의 HashSet, HashMap과 같은 자료구조에서 hashCode()는 중요한 역할을 한다. equals()를 오버라이딩할 경우, hashCode()도 함께 오버라이딩해야 한다.

hashCode() 오버라이딩 예제

class Person {
    private String name;
    
    public Person(String name) {
        this.name = name;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        Person person = (Person) obj;
        return name.equals(person.name);
    }
    
    @Override
    public int hashCode() {
        return name.hashCode();
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");
        
        System.out.println(p1.hashCode()); // 같은 값 출력
        System.out.println(p2.hashCode()); // 같은 값 출력
    }
}

equals()와 hashCode()의 관계

  • equals()가 true인 두 객체는 반드시 같은 hashCode() 값을 가져야 한다.
  • equals()가 false인 두 객체는 서로 다른 hashCode() 값을 가질 수도 있고, 동일할 수도 있다.
  • hashCode()가 같다고 해서 equals()가 반드시 true인 것은 아니다. (해시 충돌 가능)

따라서, equals()를 오버라이딩할 경우 hashCode()도 반드시 오버라이딩해야 한다. 


getClass()와 instanceof

equals() 메서드를 구현할 때, 매개변수로 받은 객체의 타입을 검사하는 방법으로 getClass()와 instanceof가 있다.

getClass() 사용

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Person person = (Person) obj;
    return name.equals(person.name);
}
  • getClass()를 사용하면 정확한 동일 타입의 객체만 비교 가능하다.
  • 즉, Person의 하위 클래스를 Person과 비교할 수 없다.

instanceof 사용

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (!(obj instanceof Person)) return false;
    Person person = (Person) obj;
    return name.equals(person.name);
}
  • instanceof를 사용하면 하위 클래스도 비교 대상에 포함된다.
  • 다형성을 고려한 비교가 가능하다.

getClass() vs instanceof

비교 기준 getClass() instanceof

하위 타입 비교 가능 여부 불가능 가능
객체의 타입 검사 엄격성 동일한 타입만 허용 하위 클래스도 허용

일반적으로 instanceof를 사용하는 것이 확장성 면에서 유리하지만, 경우에 따라 getClass()를 사용하여 더 엄격한 비교를 할 수도 있다.


정리

  • equals()는 객체의 논리적 동일성을 비교하며, 오버라이딩하지 않으면 ==과 동일한 동작을 한다.
  • hashCode()는 객체의 해시 값을 반환하며, equals()를 오버라이딩할 경우 반드시 함께 오버라이딩해야 한다.
  • equals()가 true인 객체는 동일한 hashCode() 값을 가져야 하지만, hashCode() 값이 같다고 해서 equals()가 true인 것은 아니다.
  • getClass()는 객체의 정확한 타입을 비교하고, instanceof는 상속 관계를 고려한 타입 비교가 가능하다.
728x90

'공부' 카테고리의 다른 글

단위 테스트  (0) 2025.03.01
객체와 자료 구조의 차이  (0) 2025.03.01