Java의 Equals 사용 방법 요약

6598 단어 JavaEquals
이 총결의 형식은 문제를 제기한 후에 문제의 답안을 제시하는 것이다.이것은 현재 지식을 배우는 일종의 시도로 학습을 더욱 목적으로 할 수 있다.
Q1. 언제 대상의 equals 방법을 다시 써야 합니까?
답: 일반적으로 우리가 값 비교를 해야 할 때 대상을 다시 쓰는 equals 방법이 필요합니다.예외적인 상황은'effective 자바'의 제7조'equals를 개작할 때 통용적인 약속을 지키세요'에서 명확하게 묘사되었다.
우리는 Java에서 모든 객체가 Object에 상속된다는 것을 알고 있습니다.다시 쓰지 않으면 기본 equals 코드는 다음과 같습니다.

public boolean euqals(Object obj){
 return this == obj;
}
위의 코드에서 알 수 있듯이 equal은 기본적으로'=='를 사용하여 두 대상이 같은지 아닌지를 판단한다.두 대상이 "=="를 사용하는 것은 대상의 주소입니다. 두 인용이 가리키는 대상이 같을 때만 "=="가true로 되돌아옵니다.따라서 시작의 예에서 두 대상이 equals를 가질 때 equals 방법을 다시 써야 한다.
Q2. equals를 어떻게 다시 씁니까?
답: 우선, equals 방법을 바꿀 때, 그것의 통용 약속을 만족시킬 것을 보증해야 한다.이러한 규칙은 다음과 같습니다.
자반성, 임의의 인용값 x, x.equals(x)는 반드시true입니다.
대칭성, 임의의 인용값 x와 y에 대해, y.equals(x)만 있을 때, x.equals(y)도 반드시true로 되돌아옵니다.
전달성, 임의의 인용값 x, y,z.x.equals (y) 가true, y.euqals (z) 가true로 되돌아오면 x.equals (z) 가true로 되돌아옵니다.
일치성, 임의의 인용값 x와 y에 대해 equals 비교에 사용되는 대상 정보가 수정되지 않으면, x.equals (y) 를 여러 번 호출하거나true 를 일치시키거나false 를 일치시키십시오.
비공성, 모든 대상은null과 같지 않아야 합니다.
사실 제가 생각하는 간단한 방법은 String의 equals 방법을 참조하면 됩니다. 정부에서 출판하여 각종 요구를 만족시킬 수 있습니다.그 코드는 아래와 같다

public boolean equals(Object anObject) {
 if (this == anObject) {
 return true;
 }
 if (anObject instanceof String) {
 String anotherString = (String)anObject;
 int n = count;
 if (n == anotherString.count) {
  char v1[] = value;
  char v2[] = anotherString.value;
  int i = offset;
  int j = anotherString.offset;
  while (nC != 0) {
  if (v1[i++] != v2[j++])
   return false;
  }
  return true;
 }
 }
 return false;
}
함수에 대한 설명은 다음과 같습니다.
  • 사용 = = "실참이 객체에 대한 참조인지 확인합니다."
  • instanceof를 사용하여 실참이 본 대상과 같은 종류인지 검사하고 다른 종류라면 같지 않다.
  • 실제 참조를 올바른 유형으로 변환합니다.
  • 클래스의 정의에 따라 이 대상의 값이 같은 각 조건을 검사한다.
  • 더 자세한 정보는'effective 자바'의 제7조'equals를 개작할 때 통용 약속을 지키세요'를 보십시오.
    Q3. equals를 수정할 때 무엇을 주의해야 합니까?
    답: 대체로 다음과 같은 몇 가지를 주의해야 합니다.
    equals 방법을 수정하면hashCode 방법도 수정하십시오
    우선 이것은 언어의 하나약속입니다. 이렇게 하는 이유는 이 대상이 해시 용기의 원소일 때hashCode에 의존해야 하기 때문입니다. 대상의 기본적인hashCode는 이 대상 특유의hashCode를 되돌려줍니다. 서로 다른 대상의hashCode는 되돌려주는 값이 다르고 해시 용기가 원소를 처리할 때 대상의 해시 값에 따라 대상을 다른 통에 분배합니다. 만약에 우리가 대상의hashCode를 다시 쓰지 않는다면그러면 값이 같은 대상의 해시 값도 달라져서 해시 용기에서 찾을 때 대응하는 요소를 찾을 수 없습니다.
    더 자세한 정보는'effective Java'의 8조'equals를 바꿀 때는hashCode를 항상 고쳐야 한다'를 보십시오.
    다시 쓸 때 함수 성명의 정확성을 보증합니다
    equals의 성명은
    
    public boolean equals(Object obj)
    
    매개변수 유형은 Object이며 매개변수 유형이 객체 유형이면 다음과 같습니다.
    
    class Point{
    final int x;
    final int y;
    public void Point(int x, int y)
     this.x = x;
     this.y = y;
    }
    public boolean euqals(Point obj){
      return (this.x == obj.x && this.y == obj.y);
     }
    }
    
    다음 코드 실행은 우리가 예상한 대로 실행됩니다.
    
    Point a(1, 2);
    Poinr b(1, 2);
    System.out.println(a.equals(b));//  true
    그러나 클래스 A를 용기에 넣으면 문제가 발생합니다
    
    import java.util.HashSet;
    
    HashSet<Point> coll = new HashSet<Point>();
    coll.add(a);
    System.out.println(coll.contains(b));//  false
    
    
    이것은 HashSet의 contains 방법에서 equals(Object obj)를 호출하고 Point의 equals(Object obj)는 여전히 Object의 equals이기 때문이다. 이 방법은 앞에서 이미 말했듯이 대상의 주소를 비교하기 때문에coll에서contains(b)를 호출할 때true를 얻지 못한다.
    계승 관계가 있을 때 equals의 정확성에 주의하세요
    하나의 클래스가 equals 방법을 다시 쓴 후에 다른 클래스가 이런 종류를 계승하면 앞에서 말한 대칭성을 위반할 수 있습니다. 코드는 다음과 같습니다.
    
    public class ColoredPoint extends Point { 
     private final Color color;
     public ColoredPoint(int x, int y, Color color) {
     super(x, y);
     this.color = color;
     }
    
     @Override 
     public boolean equals(Object other) {
     boolean result = false;
     if (other instanceof ColoredPoint) {
      ColoredPoint that = (ColoredPoint) other;
      result = (this.color.equals(that.color) && super.equals(that));
     }
     return result;
     }
    }
    
    
    우리가 비교할 때
    
    Point p = new Point(1, 2);
    ColoredPoint cp = new ColoredPoint(1, 2, Color.RED);
    System.out.println(p.equals(cp)); // ture
    System.out.println(cp.equals(p)); // false
    
    왜냐하면 Point를 호출할 때입니다.equals를 할 때 Point의 x와 y 좌표만 비교했고 ColoredPoint도 Point 유형이기 때문에 위의 세 번째 줄 코드가 같다. ColoredPoint를 호출할 때 Point는 ColoredPoint 유형이 아니다. 그러면 네 번째 줄 코드가 false를 출력하게 된다.
    Color 정보를 무시하고 비교하는 경우 ColoredPoint의 equals 방법을 다음과 같이 변경합니다.
    
    @overwrite
    public boolean equals(Object obj){
     if((obj instanceof Point)){
     return false;
     }
    
     if(!(obj instanceof ColoredPoint)){
     return obj.equals(this);
     }
    
     return super.equals(obj) && ((ColoredPoint)obj).color == color;
    }
    
    
    이렇게 하면 대칭성을 보장하지만 전달성, 즉 아래의 상황을 위반한다.
    
    ColoredPoint cp1 = new ColoredPoint(1, 2, Color.RED);
    Point p = new Point(1, 2);
    ColoredPoint cp2 = new ColoredPoint(1, 2, Color.BLUE);
    System.out.println(cp1.equals(p)); //true
    System.out.println(p.equals(cp2)); //true
    System.out.println(cp1.equals(cp2)); //false
    
    이러한 상황에 직면하여 대체적으로 두 가지 해결 방안이 있다. 쿠키의 문장 C가 자바에서 equals 방법의 숨겨진 함정을 피하는 방법의 마지막 하나는 Point와 ColoredPoint가 같을 가능성을 차단하는 것이다. 이것은 Point와 ColoredPoint가 다르다는 처리 방법이다.또 다른 방법은 effective Java에서 제시한 것으로 계승이 아닌 집합을 사용하여 Point를 ColoredPoint의 구성원 변수로 삼는다.현재 나는 이런 방법에 경향이 있다. 왜냐하면 집합은 계승보다 유연하고 결합이 낮기 때문이다.이 방법의 코드는 다음과 같습니다.
    
    class ColoredPoint{
     private final Point point;
     private final Color color;
    
     public Point asPoint(){
     return point;
     }
    
     public boolean equals(Object obj){
     boolean ret = false;
     if(obj instanceof ColoredPoint){
      ColoredPoint that = (ColoredPoint)obj;
      ret = that.point.equals(point) && color.equals(that.color);
     }
     return ret;
     }
    }
    
    
    ColoredPoint가 좌표를 비교해야 할 때 asPoint 방법을 호출하여 좌표로 바꾸어 비교할 수 있습니다.다른 상황은 좌표와 색깔을 비교하면 위에서 대칭성과 전달성에 관한 문제를 해결할 수 있다.
    이상은 전문의 내용입니다. 수준이 제한되어 있기 때문에 문장에 오류가 있을 수 있습니다. 지적해 주십시오. 감사합니다.
    본문이 여러분의 학습에 도움이 되기를 바랍니다. 또한 여러분이 우리를 많이 지지해 주시기를 바랍니다.

    좋은 웹페이지 즐겨찾기