항상 헷갈렸던 equals() & hashCode() 정리

Yumin Jung·2024년 12월 1일
0

ABOUT 프로그래밍

목록 보기
15/15

1. equals() 오버라이딩 했을 때 vs. 안 했을 때

1.1. equals()오버라이딩한 경우:

  • 목적: 객체의 내용(필드 값)을 비교해 논리적으로 동일한지 판단한다.

  • 예시:

    public class Person {
        private String name;
        private int age;
    
        // equals() 오버라이딩
        @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 && name.equals(person.name);
        }
    }
  • 동작: nameage 값을 비교하여 객체가 논리적으로 동일한지 판단한다.

1.2. equals()오버라이딩하지 않은 경우:

  • 목적: 기본적으로 Object 클래스의 equals() 메서드를 사용한다.

  • 기본 equals()는 객체의 참조값을 비교한다. 즉, 두 객체가 서로 다른 메모리 주소를 가리키면 false를 반환한다.

  • 예시:

    Person p1 = new Person("John", 30);
    Person p2 = new Person("John", 30);
    
    // equals()가 오버라이딩되지 않으면:
    System.out.println(p1.equals(p2)); // false (참조값이 다르므로)
  • 동작: 두 객체가 논리적으로 동일하더라도 참조값이 다르면 false를 반환한다.


2. hashCode() 오버라이딩 했을 때 vs. 안 했을 때

2.1. hashCode()오버라이딩한 경우:

  • 목적: 객체의 내용에 기반해 hashCode() 값을 계산한다. 일반적으로 equals()를 오버라이딩할 때 함께 오버라이딩한다.
  • 동작: 두 객체가 논리적으로 동일하면(equals()true를 반환) 그들의 hashCode() 값도 동일하게 보장된다.
  • 예시:
    @Override
    public int hashCode() {
        return Objects.hash(name, age); // name과 age를 기반으로 해시 코드 생성
    }
  • 동작: nameage 값에 따라 hashCode() 값을 계산하고, 같은 내용을 가진 객체는 동일한 해시 코드를 갖는다.

2.2. hashCode()오버라이딩하지 않은 경우:

  • 목적: 기본적으로 Object 클래스의 hashCode() 메서드를 사용한다.
  • 기본 hashCode()는 객체의 메모리 주소를 기반으로 해시 값을 계산한다.
  • 동작: equals()로 비교했을 때 논리적으로 동일한 객체라도 서로 다른 hashCode() 값을 가질 수 있다. 이는 Set이나 Map에서 문제가 될 수 있다.
  • 예시:
    Person p1 = new Person("John", 30);
    Person p2 = new Person("John", 30);
    
    // hashCode()가 오버라이딩되지 않으면:
    System.out.println(p1.hashCode() == p2.hashCode()); // false (메모리 주소가 다르므로 해시 코드도 다름)

3. equals()hashCode()가 동시에 오버라이딩 되었을 때

3.1. equals()hashCode()같이 오버라이딩된 경우:

  • 목적: 두 객체가 논리적으로 동일하면 두 객체의 hashCode() 값도 같아야 한다. Set이나 Map과 같은 해시 기반 컬렉션에서 일관된 동작을 보장한다.

  • 예시:

    @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 && name.equals(person.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age); // name과 age를 기반으로 해시 코드 생성
    }

3.2. equals()hashCode()같이 오버라이딩되지 않은 경우:

  • 목적: 기본 equals()는 참조값을 비교하고, 기본 hashCode()는 메모리 주소를 기반으로 해시 값을 계산한다.

  • 두 객체가 논리적으로 동일하더라도 hashCode() 값이 다를 수 있다. 이는 해시 기반 컬렉션에서 문제가 발생할 수 있다.

  • 예시:

    Person p1 = new Person("John", 30);
    Person p2 = new Person("John", 30);
    
    // equals()와 hashCode()가 모두 오버라이딩되지 않으면:
    System.out.println(p1.hashCode() == p2.hashCode()); // false (해시 코드가 다를 수 있음)

4. equals()hashCode()의 규칙

  • equals()true인 두 객체는 반드시 동일한 hashCode() 값을 가져야 한다.
  • hashCode()가 동일한 두 객체가 항상 equals()true가 되는 것은 아니다.
    • 즉, hashCode() 값이 동일하더라도 두 객체가 논리적으로 다를 수 있다. 그러나 equals()true인 객체는 반드시 동일한 hashCode() 값을 가져야 한다.

결론

  • equals()hashCode()오버라이딩하면 객체의 논리적 동등성을 기반으로 비교하고, 해시 기반 컬렉션에서 일관된 동작을 보장할 수 있다.
  • 오버라이딩하지 않으면 기본적으로 객체의 참조값이나 메모리 주소를 비교하므로, 논리적으로 동일한 객체라도 다르게 취급될 수 있다.

0개의 댓글

관련 채용 정보