2011-01-05 7 views
11

2 Objects are equal, when their type is equal and both's attribute is equal이라고 말하면 거의 10 줄의 코드를 작성해야 할 때 두통이 생깁니다. 이 방법으로 많은 수의 속성이 많은 속성으로 크게 늘어남을 쉽게 알 수 있습니다.자바 : howto는 equals()를 짧게 작성합니다

public class Id implements Node { 

     private String name; 

     public Id(String name) { 
       this.name = name; 
     } 

     public boolean equals(Object o) { 
       if (o == null) 
         return false; 
       if (null == (Id) o) 
         return false; 
       Id i = (Id) o; 
       if ((this.name != null && i.name == null) || (this.name == null && i.name != null)) 
         return false; 
       return (this.name == null && i.name == null) || this.name.equals(i.name); 
     } 

} 
+2

올바른 구현을위한 내 대답을 참조하십시오. 잘못된 유형으로 무언가를 전송하면 null이 아닌 런타임 예외 (ClassCastException)가 발생합니다. 환상적인 *** 설명을위한 효과적인 자바를 읽으십시오. – Tom

+1

Btw - 나는 실제적인 챕터에 대한 효과적인 자바에서 내 대답에 링크 :-). – Tom

답변

10

클릭 : 어쩌면 당신이 의미

  if (o == null) 
        return false; 
      if (null == (Id) o) 
        return false; 

예를 들어, 평민 - 랭 또한 EqualsBuilder

있으며,이 두 줄은 같은 일을 표시 소스 "->"은 hashCode() 및 equals()를 생성합니다. ". equals()를 자동으로 생성하는 많은 옵션이 있습니다.

+3

제 경험상, 생성 된 클래스와 동기화되지 않는 경향이 있습니다. 그러나 그것은 좋은 코드 리뷰로는 해결할 수없는 것이 아닙니다. 그리고 나는 손으로 쓴 사람이 쉽게 같은 문제를 가질 수 있다고 생각합니다. 가장 쉬운 방법은 – sblundy

+0

입니다. 직접적으로 중요하지 않은 것을 신경 쓰지 않아도됩니다. 어쨌든, 생성 된 코드는 그다지 작지 않습니다. Java에서 일반적인 경우 인 것 같습니다 ... – erikbwork

+0

이 응답에 대해 두 가지를 말해 보겠습니다. (1) 생성 된 코드가 항상 올바른 것으로 생각하지 마십시오. (2) 해독 성은 또 다른 관심사입니다. – Tom

9

당신을위한 라이브러리가 있습니다. "당신은 이클립스를 사용하는 경우

  if (o == null) 
        return false; 
      if (this == o) 
        return true; 
+0

첫 번째 매개 변수가 param인지 확인해야하고 두 번째 매개 변수가 형식을 확인해야합니다. Java를 배울 때 캐스트는 일치하지 않는 유형에서 null을 반환했습니다. 그러나 이미 내가 발견 한 단위 테스트를 통해 더 이상 그렇지 않은 것으로 보입니다. – erikbwork

+0

@erikb : ClassCastException이 발생합니다. 다음과 같이 클래스가 같은지 여부 만 확인할 수 있습니다. this.getClass() == o.getClass(). 서브/수퍼 클래스는 약간의 주름을 추가합니다. – sblundy

+0

@sblundy : (IIRC)가 getClass() 대신'instanceof'를 사용해야하는 이유에 대한 설명이있는 효과적인 java를 읽으십시오. Josh Bloch는'equals()'를 구현하는 올바른 방법을 설명하는 훌륭한 작업을하고 있습니다. 읽지 않았다면 거의 확실하게 뭔가를 배울 것입니다. – Tom

12

Google의 구아바 라이브러리에는 null이 처리되는 Objects#equalObjects 클래스가 있습니다. 그것은 정말 작은 것들을 얻는 데 도움이됩니다. 귀하의 예를 들면 다음과 같습니다.

@Override public boolean equals(Object other) { 
    if (!(other instanceof Id)) { 
    return false; 
    } 
    Id o = (Id) other; 
    return Objects.equal(this.name, o.name); 
} 

설명서는 here입니다.

hashCodetoString도 도움이되는 Objects#hashCodeObjects#toStringHelper입니다.

Effective Java 2nd Edition on how to write equals()도 참조하십시오.

+1

효과적인 Java의 관련 챕터에 링크하기 위해 필자의 대답에서 링크를 업데이트했습니다! 이제 그것을 읽지 않을 변명의 여지가 없습니다 :-). – Tom

+0

JDK 7과 비슷한 [Objects.equals] (http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html#equals (java.lang.Object, % 20java.lang) .Object)) 메서드를 호출합니다. – pesche

4

Project Lombok도 현재 클래스/소스 코드와 동기화되는 이점을 가진 @EqualsAndHashCode 주석을 사용하여 equalshashCode 생성기를 사용합니다. 구현 세부 사항에 대해서는 확신 할 수 없지만 크래프트를 줄여야하는지 확실히 조사 할 가치가 있습니다.

1

더 간단한 방법 (코드 생성 제외) 일 수 있습니다.

public boolean equals(Object o) { 
    return o instanceof Id 
     && (name == null ? ((Id)o).name == null : name.equals(((Id)o).name); 
} 
+0

이것은 (적어도 가독성 측면에서는) 일반적으로 잘 정의되지 않습니다. 하나의 필드가있는 경우에는 줄이 작습니다. 내 대답은 여전히 ​​여기서도 적용됩니다 :'return o instanceof Id && Objects.equal (name, ((id) o) .name); ' – Tom

+0

@Tom, 당신의 대답은 더 좋아질 것이지만 추가 라이브러리가 필요합니다. 도우미 방법 같은 일을;) 나는 이것이 질문에 대한 가장 짧은 완전한 대답이라고 생각합니다. –

+0

+1 : 지금까지 가장 정확한 올바른 구현 ((null instanceof Object) == false). name이 결코 null이 될 수 없다면 이것은 더 단순화 될 수 있다는 것을 주목할 필요가 있습니다. – meriton

관련 문제