Item10
equals는 일반 규약을 지켜 재정의하라
- equals 메서드 재정 의는 곳곳에 함정이 도사리고 있어 끔찍한 결과를 초래한다.
- 따라서 아예 재정의를 하지 않는 것이 더 좋을 때도 있다.
1 equals 재정의 하지 않는 경우
1.1 각 인스턴스가 본질적으로 고유할 경우
- 값을 표현하는 게 아닌 동작하는 개체를 표현하는 클래스일때
- 예:
Thread
- 예:
1.2 인스턴스의 '논리적 동치성'을 검사할 일이 없을 경우
- 논리적 동치성: 두 객체를 비교할 때 두 객체가 같은지가 아니라 값이 같음을 비교하는 경우
- 주로 값 클래스를 논리적 동치성으로 비교한다
- 값 클래스: Integer, String 등
- 객체의 식별성: 두 객체를 비교할 때 두 객체가 같은지 비교하는 경우
java.util.regex.Pattern의equals는 논리적 동치성 검사가 필요없다라고 판단하여 equals를 재정의하지 않았다
Integer.java
- 값 클래스 Integer의 equals 메소드는 논리적 동치성을 따진다
- 두 객체간의 값이 같은지를 비교하고 있다
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
1.3 상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 들어맞는 경우
AbstractList.java
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
}
- 대부분의 List의 구현체들은 AbstractList로부터 equals를 상속받아 그대로 쓴다