> Java > java지도 시간 > equals() 메서드 재정의

equals() 메서드 재정의

高洛峰
풀어 주다: 2016-12-16 10:38:07
원래의
1400명이 탐색했습니다.

1. 왜 equals() 메소드를 다시 작성해야 합니까?

클래스의 멤버 변수를 기준으로 두 클래스의 인스턴스가 동일한지 판단하는 등 두 객체가 논리적으로 동일한지 여부를 판단합니다. 그러나 상속된 Object의 equals 메서드는 두 참조 변수가 인스턴스인지 여부만 확인할 수 있습니다. 동일합니다. 이런 방식으로 우리는 종종 equals() 메서드를 재정의해야 합니다.

중복된 ​​개체 없이 컬렉션에 요소를 추가하면 개체가 컬렉션에 저장되는 경우가 많습니다. 먼저 컬렉션에 알려진 개체가 있는지 확인해야 하므로 equals 메서드를 재정의해야 합니다.

2. equals() 메소드를 어떻게 재정의하나요?

equal 메서드 재정의 요구 사항:
1. 재귀성: x.equals(x)는 null이 아닌 참조 x에 대해 true를 반환해야 합니다.
2. 대칭: x와 y에 대한 참조의 경우 x.equals(y)가 true를 반환하면 y.equals(x)도 true를 반환해야 합니다.
3. 전이성: x, y 및 z 참조에 대해 x.equals(y)가 true를 반환하고 y.equals(z)가 true를 반환하면 x.equals(z)도 true를 반환해야 합니다.
4. 일관성: x와 y가 참조하는 객체가 변경되지 않은 경우 x.equals(y)를 반복적으로 호출하면 동일한 결과가 반환되어야 합니다.
5. Null 허용 여부: Null이 아닌 참조 x의 경우 x.equals(null)은 false를 반환해야 합니다.

형식:


Java 코드

public boolean equals(Object obj) {  
    if(this == obj)  
        return false;  
    if(obj == null)  
        return false;  
    if(getClass() != obj.getClass() )  
        return false;  
    MyClass other = (MyClass)obj;  
    if(str1 == null) {  
         if(obj.str1 != null) {  
              return false;  
         }  
    }else if (!str1.equals(other.str1) )  
             return false;  
     }  
    if(var1 != other.var1)  
        return false;  
    return true;  
}
로그인 후 복사

equal 메서드를 유지하면서 하위 클래스에 새로운 기능이 추가되면 다음과 같습니다. 더 복잡합니다.


다음으로 위의 관례를 예를 통해 이해해 보겠습니다. 변경 불가능한 간단한 2D 포인트 클래스로 시작합니다:

public class Point{ 
  private final int x; 
  private final int y; 
  public Point(int x, int y){ 
    this.x = x; 
    this.y = y; 
  } 
  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{ 
  private Color color; 
  public ColorPoint(int x, int y, Color color){ 
    super(x, y); 
    this.color = color; 
  } 
  //override equasl() 
  public boolean equals(Object o){ 
    if(!(o instanceof ColorPoint)) 
     return false; 
    ColorPoint cp = (ColorPoint)o; 
    return super.equals(o) && cp.color==color; 
  } 
}
로그인 후 복사


실제 매개변수가 동일한 위치와 색상을 가진 다른 색상 포인트인 경우에만 true를 반환하도록 equals 메소드를 재정의합니다. 하지만 이 방법의 문제점은 정상 점과 유색 점을 비교하거나 그 반대의 경우 다른 결과를 얻을 수 있다는 것입니다.

public static void main(String[] args){ 
  Point p = new Point(1, 2); 
  ColorPoint cp = new ColorPoint(1, 2, Color.RED); 
  System.out.println(p.equals(cp)); 
  System.out.println(cp.eqauls(p)); 
}
로그인 후 복사

실행 결과:
true
false
이러한 결과는 분명히 대칭을 위반합니다. 이 문제를 해결하려면 다음을 시도할 수 있습니다. "혼합 비교"를 수행할 때 ColorPoint.equals가 색상 정보를 무시하도록 합니다.

public boolean equals(Object o){ 
  if(!(o instanceof Point)) 
    return false; 
  //如果o是一个普通点,就忽略颜色信息 
  if(!(o instanceof ColorPoint)) 
    return o.equals(this); 
  //如果o是一个有色点,就做完整的比较 
  ColorPoint cp = (ColorPoint)o; 
  return super.equals(o) && cp.color==color; 
}
로그인 후 복사

어떻게 될까요? 이 방법의 결과는? 먼저 테스트해 보겠습니다.

public static void main(String[] args){ 
  ColorPoint p1 = new ColorPoint(1, 2, Color.RED); 
  Point p2 = new Point(1, 2); 
  ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE); 
  System.out.println(p1.equals(p2)); 
  System.out.println(p2.equals(p1)); 
  System.out.println(p2.equals(p3)); 
  System.out.println(p1.eqauls(p3)); 
}
로그인 후 복사

실행 결과:
true
true
true
false

이 방법은 대칭성을 제공하지만 전이성 비용(관례에 따라 p1.equals(p2) 및 p2.eqauals(p3)은 모두 true를 반환하고 p1.equals(p3)도 true를 반환해야 함) 어떻게 해결하나요?

사실 이는 객체지향 언어의 등가관계에 대한 기본적인 질문입니다. 같음 규칙을 유지하면서 새 기능을 추가하기 위해 인스턴스화 가능한 클래스를 확장하는 쉬운 방법은 없습니다. 새로운 해결책은 더 이상 ColorPoint가 Point를 확장하도록 허용하지 않고 ColorPoint에 개인 Point 필드와 공용 보기 메서드를 추가하는 것입니다.

public class ColorPoint{ 
  private Point point; 
  private Color color; 
  public ColorPoint(int x, int y, Color color){ 
    point = new Point(x, y); 
    this.color = color; 
  } 
  //返回一个与该有色点在同一位置上的普通Point对象 
  public Point asPoint(){ 
    return point; 
  } 
  public boolean equals(Object o){ 
    if(o == this) 
     return true; 
    if(!(o instanceof ColorPoint)) 
     return false; 
    ColorPoint cp = (ColorPoint)o; 
    return cp.point.equals(point)&& 
             cp.color.equals(color); 
  } 
}
로그인 후 복사

또 다른 솔루션이 있습니다. 해결책은 Point를 다음과 같이 디자인하는 것입니다. 추상 클래스를 사용하면 같음 계약을 위반하지 않고 추상 클래스의 하위 클래스에 새 기능을 추가할 수 있습니다. 추상 클래스는 클래스의 인스턴스를 만들 수 없기 때문에 위에서 언급한 문제가 발생하지 않습니다.

equal 메소드 재정의의 핵심 사항:
1. == 연산자를 사용하여 "실제 매개변수가 객체에 대한 참조인지 여부"를 확인합니다.

2.실제 매개변수가 null인지 확인
3.instanceof 연산자를 사용하여 "실제 매개변수가 올바른 유형인지" 확인합니다.
4. 실제 매개변수를 올바른 유형으로 변환합니다.
5. 이 클래스의 각 "키" 필드에 대해 실제 매개변수의 필드가 현재 개체의 해당 필드 값과 일치하는지 확인합니다
. float 또는 double이 아닌 기본 유형의 필드에 대해 == 연산자
를 사용하여 객체 참조 유형의 필드에 대해 float 유형에 대해 참조된 객체의
메소드를 재귀적으로 호출할 수 있습니다. 필드의 경우 먼저 Float.floatToIntBits를 사용하여 int 유형 값으로 변환합니다.
그런 다음 == 연산자를 사용하여 int 유형 값을 비교합니다. double 유형 필드의 경우 먼저
Double.doubleToLongBits를 사용하여 Long 유형 값으로 변환합니다. 그런 다음 == 연산자를 사용하여
긴 유형의 값을 비교합니다.
6. 같음 메서드를 작성한 후에는 세 가지 질문을 스스로에게 물어봐야 합니다. 대칭형, 추이형, 일관성이 있습니까? (나머지 두 가지 특성은 대개 저절로 충족됩니다.) 대답이 '아니요'인 경우 이러한 특성이 만족되지 않는 이유를 찾아낸 후 equals 메서드의 코드를 수정해 보세요.



equals() 메서드 다시 작성과 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿