@Override public boolean equals(Object o){
throw new AssertionError();
}
(String, Integer와 같은 경우 값을 비교하고 싶을 때.
하지만, enum과 같이 객체가 하나만 생성되는 것이 보장되었을 때에는 equals 메소드를 재정의할 필요 없다. -> 논리적 동치성 == 객체 식별성
public final class CaseInsensitiveString {
private final String;
public CaseInsensitiveString(String s){
this.s = Objects.requireNonNull(s);
}
@Override
public boolean equals(Obejct o){
if( o instanceof CaseInsesitiveString){
return s.eqaulsIgnoreCase(
((CaseInsensitiveString) o).s);
if (o instanceof String)
return s.equalsIgnoreCase((String) o);
return false;
)
}
}
}
CaseInsenitiveString cis = new CaseInsensitiveString("Polish");
String s = "Polish";
System.out.println("cis.equals(s) = " + cis.equals(s)); //true
System.out.println("s.equals(cis) =" + s.equals(cis)); //false
String 객체에서는 CaseIntensitiveString의 존재를 모르기 때문에 대칭성이 위반된다. 따라서, cis.equals(s)도 false로 나오게 다시 equals 메소드를 정의한다.
@Override
public boolean equals(Object o){
return o instanceof CaseInsensitiveString &&
((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}
1=2, 2=3, 1=2=3
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;
}
}
위와 같이 Point객체끼리의 equals를 재정의하는 것은 간단하다. 하지만, point를 상속받는 클래스를 가정하여 생각해보자.
public class ColorPoint extends Point{
private final Color color;
pulbic ColorPoint(int x, int y, Color color){
super(x,y);
this.color = color;
}
@Overrid public boolean equals(Object o){
if(!(o instanceof Point))
return false;
if(!(o instanceof ColorPoint))
rturn false;
return super.eqauls(o) && ((ColorPoint) o).color == color;
}
}
위에서 정의한 equals 메소드는 색깔을 무시하고 비교를 하기 때문에, 추이성에 위반된다.
ColorPoint p1 = new ColorPoint(1,2,COLOR.RED);
Point p2 = new Point(1,2);
ColorPoint p3 = new ColorPoint(1,2,COLOR.BLUE);
p1.equals(p2); // true
p2.equals(p3); // true
p1.equals(p3); // false
해결법 : ColorPoint에 Point필드를 추가하여 추이성을 만족시키자.
상속 대신 컴포지션을 사용하자
public class ColorPoint{
private final Point point;
private Color color;
public ColorPoint(int x, int y, Color color){
Point = new Point(x,y);
this.color = Objects.requireNonNull(color);
}
public Point asPoint(){
return point;
}
@Override
public boolean equals(Object o){
if(!(o instanceof ColorPoint)
return false;
ColorPoint cp = (ColorPoint) o;
return cp.point.equas(point) && cp.color.equals(color);
}
}
float, double 같은 경우는 compare함수를 통해 비교하자. float.equals 와 double.equals는 오토박싱을 수반하기 때문에 성능상 좋지않다.
null을 허용하는 필드는 Object.equals()를 통해 nullPointException을 방지하자.
필드들을 비교해나갈 때, 비교하는 비용이 싼 필드들을 먼저 비교하자.