재정의하지 않는것이 최선인 상황
1.각 인스턴스가 본질적으로 고유하다
2.인스턴스의 논리적 동치성을 검사할 일이없다.
3.상위 클래스에서 재정의한 equals가 하위클래스에도 딱 들어맞는다.
4.클래스가 private이거나 package-private이고 메서드를 호출할 일이없다
equals메서드 재정의 규약
-->객체는 자기자신과 같아야한다
-->두 객체는 서로에대한 동치여부에 똑같이 답해야한다는 뜻
즉 첫번째객체와 두번째 객체가 같고, 두번째와세번째가 같다면
첫번째와 세번째 객체도 같아야한다는 의미
대칭성 위배
public final class CaseInsenstiveString {
private final String s;
public CaseInsenstiveString(String s) {
this.s = Objects.requireNonNull(s);
}
//대칭성 위배
@Override
public boolean equals(Object o) {
if (o instanceof CaseInsenstiveString)
return s.equalsIgnoreCase(((CaseInsenstiveString) o).s);
if(o instanceof String) //한방향으로만 작동
return s.equalsIgnoreCase((String)o);
return false;
}
}
해결코드
@Override
public boolean equals(Object o) {
return o instanceof CaseInsenstiveString && ((CaseInsenstiveString)o).s.equalsIgnoreCase(s);
}
1)2차원에서 점을 표현하는 클래스가 있다고가정
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if(!(o instanceof Point))
return false;
Point p=(Point) o;
return p.x==x && p.y==y;
}
}
public class ColorPoint extends Point{
public ColorPoint(int x, int y,Color color) {
super(x, y);
this.color=color;
}
}
대칭성을위배한 코드
@Override
public boolean equals(Object o) {
if(!(o instanceof ColorPoint))
return false;
return super.equals(o)&&((ColorPoint)o).color==color;
}
추이성 위배
@Override
public boolean equals(Object o) {
if(!(o instanceof ColorPoint))
return false;
//return super.equals(o)&&((ColorPoint)o).color==color;
//o가 일반 Point면 색상을 무시하고 비교한다.
if(!(o instanceof ColorPoint))
return o.equals(this);
//o가 ColorPoint면 색상까지 비교한다.
return super.equals(o) && ((ColorPoint)o).color==color;
}
-->두객체가 같다면 앞으로도 영원히 같아야한다는 의미
1)클래스가 불변이는 가변이든 equals의 판단에 신뢰할수없는 자원이끼어들게 해서는 안된다.
2)null-아님은 이름처럼 모든 객체가 null과 같지 않아야한다는 뜻
//명시적 null검사는 필요없다
@Override
public boolean equals(Object o) {
if(o==null)
return false;
}
//묵시적 null 검사
@Override
public boolean equals(Object o) {
if(!(o instanceof MyType))
return false;
MyType mt=(MyType)o;
}
3)instanceOf는 첫번째 피연산자가 null이면 false를 반환
4)입력이 null이면 타입확인단계에서 false를 반환하기때문에 null검사를 명시적으로 할 필요가없다
1)==연산자를 사용해 입력이 자기 자신의 참조인지 확인한다.
2)instanceOf 연산자로 입력이 올바른 타입인지확인한다.
3)입력을 올바른 타입으로 형변환 한다.
4)입력 객체와 자기자신의 대응되는 '핵심'필드들이 모두 일치하는지 하나씩 검사한다.
5)equals를 재정의할땐 haseCode도 반드시 재정의하자