-
[Java] equals와 hashCodeLanguage/Java 2023. 9. 27. 15:16
equals와 hashCode는 모든 클래스의 부모인 Object 클래스에 정의되어 있는 메소드다. 각 메소드는 다음과 같은 기능을 한다.
- equals: 두 객체가 같은지 비교하고 boolean을 리턴한다. 오버라이딩하지 않을 경우 두 객체의 주소값을 비교한다.
- hashCode: 객체의 고유값을 리턴한다. 오버라이딩하지 않을 경우 객체의 메모리 주소를 바탕으로 한 해시값을 리턴한다.
따라서 equals와 hashCode를 오버라이딩하지 않고 사용하면 객체의 속성값이 아닌 주소값을 비교한 결과를 리턴하게 된다.
// Person 클래스 public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } } // Person 인스턴스 비교 public static void main(String[] args) { Person p1 = new Person("철수", 20); Person p2 = new Person("철수", 20); // p1객체와 p2 객체의 속성값이 같지만, equals와 hashCode를 오버라이딩 하지 않았기에 주소값을 비교한다. System.out.println(p1.equals(p2)); // false }
객체의 주소값이 아닌 속성값을 비교하고 싶다면 equals와 hashCode를 오버라이딩 해야 한다.
IDE의 기능을 활용하여 equals와 hashCode를 쉽게 오버라이딩 할 수 있다.// equals와 hashCode를 오버라이딩한 클래스 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 o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, age); } } // Person 인스턴스 비교 public static void main(String[] args) { Person p1 = new Person("철수", 20); Person p2 = new Person("철수", 20); System.out.println(p1.equals(p2)); // true }
equals를 오버라이딩할 때 hashCode도 오버라이딩 해야 하는 이유
객체의 속성값으로 비교하기 위해 equals를 오버라이딩할 때는 반드시 hashCode의 값도 오버라이딩 해줘야 한다. 위 예제에서는 equals만 오버라이딩 해도 원하는 결과를 받을 수 있는데, 왜 hashCode도 오버라이딩 해야 할까?
그 이유는 hashCode를 사용하는 Collections 때문이다. HashMap, HashTable, HashSet과 같은 자료구조는 객체의 같음을 판단할 때 hashCode가 같은지 확인하고, equals의 결과가 true인지를 확인한다.
만약 equals만 재정의한다면 hashSet에는 속성값이 같은 객체가 여러개 들어가게 될 것이다.
// hashCode를 오버라이딩 하지 않은 Person 클래스 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 o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } } public static void main(String[] args) { Set<Person> set = new HashSet<>(); Person p1 = new Person("철수", 20); Person p2 = new Person("철수", 20); set.add(p1); set.add(p2); System.out.println(set.size()); // 1이 출력 돼야 하지만 hashCode를 오버라이딩 하지 않아 2가 출력된다. }
참조
'Language > Java' 카테고리의 다른 글
[Java] 금융 거래에는 BigDecimal을 사용하자. (0) 2024.02.19 [Java] 객체지향 설계원칙, SOLID 알아보기 (0) 2024.01.11 [Java] 객체지향 프로그래밍에 대해 알아보자 (0) 2023.12.27 [Java] DateTimeFormatter로 LocalDateTime 포맷팅 하기 (0) 2023.07.31