public boolean equals(Object obj) {
return (this == obj);
}
@Test
void test(){
Map<String, Integer> map1 = new HashMap<>();
map1.put("1", 1);
map1.put("2", 2);
Map<String, Integer> map2 = new HashMap<>();
map2.put("1", 1);
map2.put("2", 2);
Assertions.assertThat(map1).isEqualTo(map2);
}
isEqualTo로 HashMap을 비교하면 success가 떨어진다.
왜냐면 isEqualTo는 동등비교이기 때문이다.
그런데 내가 만든 TestObject객체로 isEqualTo비교 시 Exception이 발생하였다
@Getter
@AllArgsConstructor
public class TestObject {
private String first;
}
@Test
void test2(){
TestObject testObject = new TestObject("1");
TestObject testObject2 = new TestObject("1");
Assertions.assertThat(testObject).isEqualTo(testObject2);
}
아니 똑같은 동등비교인데 (new 연산자로 생성되는(주소값이 다른))
왜 TestObject는 안되는걸까 의문이 생겼다.
궁금하기에 isEqualTo를 까보면 아래와같다.
isEqualTo를 타고 들어가다보면
StandardComparisonStrategy 의 areEqual로 객체를 비교하는데 해당 내용을 보니
@Override
public boolean areEqual(Object actual, Object other) {
if (actual == null) return other == null;
// 생략 //
return actual.equals(other);
}
이렇게 actual.equals로 비교를 하는것이다.
Map같은 경우 equals로 값을 꺼내서 비교하는 코드가 선언되어있다.
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<?,?> m = (Map<?,?>) o;
if (m.size() != size())
return false;
try {
for (Entry<K, V> e : entrySet()) {
K key = e.getKey();
V value = e.getValue();
if (value == null) {
if (!(m.get(key) == null && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
return true;
}
하지만 TestObject의 경우 equals 메소드를 선언하지 않았기에
가장 최상단에 있는 Object의 equals를 비교하게된다.
public boolean equals(Object obj) {
return (this == obj);
}
그렇기에 TestObject가 같지 않다고 Exception이 발생하는 것이다.
해결방법은 간단하다.
@EqualsAndHashCode를 추가하여 동등비교 자동생성 메서드를 만들어주는것이다.
@Getter
@AllArgsConstructor
@EqualsAndHashCode // 추가
public class TestObject {
private String first;
}