equals 메서드
==
연산자는 객체의 주소 값만을 비교하기 때문에 객체의 상태가 동일한지 알 수 없다. 이때 equals
메서드를 오버라이딩 하여 객체의 동등성 비교를 위한 로직을 구현할 수 있다.
다음과 같이 equals
메소드 내부구현에는 두 객체의 동등성을 어떻게 정의할 것인가 에 대한 내용을 담게된다.
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) {
return false;
}
Product product = (Product)o;
return id != null && Objects.equals(id, product.id);
}
위의 코드에서는 id 값을 통해 객체의 동등성을 확인하도록 equals 메서드를 정의하였다.
주의사항
equals 메서드의 설명에는 다음과 같이 equals를 정의하면 hashcode를 정의하라는 구절이 있다.
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
만약 equals만 재정의하고 hashcode를 재정의하지 않는다면, HahsMap, HashSet, Hashtable 과 같은 해시 기반의 컬렉션에서 객체가 제대로 동작하지 않을 수 있다.
HashCode를 정의하지 않는다면
다음의 Sample 클래스는 equals만 정의하고 hashCode를 정의하지 않았다.
Sample.class
class Sample {
String key;
String value;
public Sample(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Sample sample = (Sample) o;
return Objects.equals(key, sample.key);
}
}
이때 Sample 클래스를 활용해 HashSet을 만들고 테스트를 해보면
Main 함수
public static void main(String[] args) {
HashSet<Sample> samples = new HashSet<>();
Sample sample1 = new Sample("a", "b");
Sample sample2 = new Sample("a", "b");
samples.add(sample1);
System.out.println(sample1.hashCode());
System.out.println(sample2.hashCode());
System.out.println(samples.contains(sample2));
}
위의 코드에서 sample1
, sample2
객체는 같은 key
필드 값을 가지고 있다.key
필드를 통해 객체의 동등성을 비교하기 때문에 결과는 true
가 나오길 기대하지만, 실제 결과는 false
이다.
실행 결과
798154996
681842940
false
Smaple 클래스는 hashCode를 오버라이딩 하지 않아 서로 다른 hashCode를 갖고있기 때문이다.
수정후
hashCode를 오버라이딩하고 실행하면 다음과 같이 기대한 결과가 나오는것을 확인할 수 있다.
class Sample {
String key;
String value;
public Sample(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Sample sample = (Sample) o;
return Objects.equals(key, sample.key);
}
@Override
public int hashCode() {
return Objects.hash(key);
}
}
실행결과
128
128
true
참고
'Java & Kotlin' 카테고리의 다른 글
[Java] HotSpot VM의 Survivor영역은 왜 2개일까? (0) | 2023.08.28 |
---|---|
[Kotlin] Kotlin DSL과 Kotest로 Java RestDocs 테스트 리팩토링 하기 (2) | 2023.01.15 |
[Java] orElse 와 orElseGet의 차이점 (0) | 2022.08.25 |
[Java] StringBuilder vs StringBuffer (0) | 2022.08.22 |
[Java] 객체지향 프로그래밍 - 2 (0) | 2022.08.22 |