Java Equals () 메소드를 우선적으로 재정의합니다 - 작동하지 않습니까?
-
06-07-2019 - |
문제
나는 equals()
오늘날 잘 테스트 된 클래스라고 생각한 것은 충돌하고 추적하는 데 오랜 시간이 걸렸던 버그를 일으킨 방법입니다.
완전성을 위해, 나는 IDE 또는 디버거를 사용하지 않았습니다. 시간은 매우 제한적이었고 학교 프로젝트였습니다.
어쨌든 -
나는 포함 할 수있는 기본 쇼핑 카트를 개발하고있었습니다. ArrayList
의 Book
사물. 구현하기 위해 addBook()
, removeBook()
, 그리고 hasBook()
카트의 방법, 나는 Book
이미 존재했습니다 Cart
. 그래서 나는 간다 -
public boolean equals(Book b) {
... // More code here - null checks
if (b.getID() == this.getID()) return true;
else return false;
}
모두 테스트에서 잘 작동합니다. 나는 6 개의 객체를 만들고 데이터로 채 웁니다. 많은 추가, 제거, () 작업이 Cart
그리고 모든 것이 잘 작동합니다. 나는 당신이 할 수 있다는 것을 읽었습니다 어느 쪽이든 equals(TYPE var)
또는 equals(Object o) { (CAST) var }
그러나 그것이 효과가 있기 때문에 너무 중요하지 않다고 가정했습니다.
그런 다음 문제를 해결했습니다. Book
객체 뿐 그만큼 ID
책 수업 내에서. 다른 데이터는 입력되지 않습니다. 기본적으로 다음은 다음과 같습니다.
public boolean hasBook(int i) {
Book b = new Book(i);
return hasBook(b);
}
public boolean hasBook(Book b) {
// .. more code here
return this.books.contains(b);
}
갑자기, equals(Book b)
메소드가 더 이상 작동하지 않습니다. 좋은 디버거없이 추적하는 데 시간이 오래 걸렸습니다. Cart
클래스는 올바르게 테스트하고 정확했습니다. 스와핑 후 equals()
다음에 대한 방법 :
public boolean equals(Object o) {
Book b = (Book) o;
... // The rest goes here
}
모든 것이 다시 작동하기 시작했습니다. 이 방법이 책 매개 변수를 명확하게 받아들이지 않기로 결정한 이유가 있습니까? ~였다 ㅏ Book
물체? 유일한 차이점은 동일한 클래스 내에서 인스턴스화되었으며 하나의 데이터 구성원으로 만 채워진 것 같습니다. 나는 매우 혼란 스럽습니다. 제발, 약간의 빛을 흘리나요?
해결책
Java에서 equals()
상속 된 메소드 Object
이다:
public boolean equals(Object other);
다시 말해, 매개 변수는 유형이어야합니다. Object
.
그만큼 ArrayList
올바른 평등 방법을 사용합니다. 여기서 항상 제대로 무시하지 않은 방법을 호출했습니다. Object
동등합니다.
방법을 올바르게 무시하지 않으면 문제가 발생할 수 있습니다.
나는 매번 다음과 같다.
@Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof MyClass))return false;
MyClass otherMyClass = (MyClass)other;
...test other properties here...
}
사용 @Override
주석은 바보 같은 실수로 톤을 도울 수 있습니다.
슈퍼 클래스 또는 인터페이스의 메소드를 재정의한다고 생각할 때마다 사용하십시오. 이렇게하면 잘못한 경우 컴파일 오류가 발생합니다.
다른 팁
Eclipse를 사용하면 상단 메뉴로 이동하십시오.
소스 -> equals () 및 hashcode () 생성
당신의 질문에 약간 주제가되었지만 어쨌든 언급 할 가치가있을 것입니다.
커먼즈 랭 Equals 및 해시 코드를 재정의하는 데 사용할 수있는 몇 가지 훌륭한 방법이 있습니다. 체크 아웃 equalsbuilder.reflectionequals (...) 그리고 HashcodeBuilder.reflectionhashcode (...). 과거에 나에게 많은 두통을 저장했습니다. 물론 ID에서 "동등한"을하고 싶다면 상황에 맞지 않을 수도 있습니다.
또한 사용해야한다는 데 동의합니다 @Override
주석을 우선시 할 때마다 (또는 다른 방법).
보일러 플레이트 코드를 저장하는 또 다른 빠른 솔루션은 다음과 같습니다 Lombok Equalsandhashcode 주석. 쉽고 우아하며 사용자 정의 할 수 있습니다. 그리고 IDE에 의존하지 않습니다. 예를 들어;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(of={"errorNumber","messageCode"}) // Will only use this fields to generate equals.
public class ErrorMessage{
private long errorNumber;
private int numberOfParameters;
private Level loggingLevel;
private String messageCode;
참조 옵션 평등에 사용할 필드를 사용자 정의 할 수 있습니다. Lombok은 avalaible입니다 Maven. 그냥 추가하십시오 제공 범위:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.14.8</version>
<scope>provided</scope>
</dependency>
Android Studio에는 Alt + Insert ---> Equals 및 Hashcode가 있습니다.
예시:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Proveedor proveedor = (Proveedor) o;
return getId() == proveedor.getId();
}
@Override
public int hashCode() {
return getId();
}
고려하다:
Object obj = new Book();
obj.equals("hi");
// Oh noes! What happens now? Can't call it with a String that isn't a Book...
그만큼 instanceOf
진술은 종종 평등을 구현하는 데 사용됩니다.
이것은 인기있는 함정입니다!
문제는 사용하는 것입니다 instanceOf
대칭 규칙을 위반합니다.
(object1.equals(object2) == true)
경우에만 (object2.equals(object1))
첫 번째 평등이 참이고 Object2는 OBJ1이 속한 클래스의 서브 클래스 인스턴스 인 경우 두 번째 평등은 False를 반환합니다!
OB1이 속한 것으로 간주되는 클래스가 최종으로 선언 된 경우이 문제는 발생할 수 없지만 일반적으로 다음과 같이 테스트해야합니다.
this.getClass() != otherObject.getClass();
그렇지 않은 경우, False를 반환하고 그렇지 않으면 평등을 비교하기 위해 필드를 테스트하십시오!
RecordId는 객체의 속성입니다
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Nai_record other = (Nai_record) obj;
if (recordId == null) {
if (other.recordId != null)
return false;
} else if (!recordId.equals(other.recordId))
return false;
return true;
}