나는 equals()
오늘 시험 법 에 대한 흥미롭고 매우 실망스러운 문제 에 부딪쳤다.
완벽 함을 위해 IDE 또는 디버거를 사용하지 않았습니다. 좋은 구식 텍스트 편집기와 System.out입니다. 시간은 매우 제한되어 있었고 학교 프로젝트였습니다.
어쨌든-
나는 포함 할 수있는 기본적인 쇼핑 카트를 개발하고 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 개의 객체를 만들어 데이터로 채 웁니다. 에 대해 많은 추가, 제거, has () 작업을 수행하면 Cart
모든 것이 잘 작동합니다. 나는 당신 이 equals(TYPE var)
또는equals(Object o) { (CAST) var }
하지만이 작동 된 이후, 너무 많이 중요하지 않았다 것으로 가정.
그럼 난 문제로 실행 – 내가 만드는 데 필요한 Book
와 개체를 만ID
Book 클래스 내에서한다. 다른 데이터는 입력되지 않습니다. 기본적으로 다음과 같습니다.
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
. 이를 재정의 라고합니다 . 귀하의 방법 public boolean equals(Book other)
은 오버로드 라는 것을 수행합니다.equals()
.
ArrayList
오버라이드 (override) 사용 equals()
방법 (자사에 대한 예를 내용을 비교 contains()
하고 equals()
, 방법) 하지 과부하 사람. 대부분의 코드에서 Object
equals를 올바르게 재정의하지 않은 코드를 호출하는 것은 좋지만와 호환되지 않습니다 ArrayList
.
따라서 메소드를 올바르게 재정의하지 않으면 문제가 발생할 수 있습니다.
매번 다음을 무시합니다.
@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
주석을 사용하면 바보 같은 실수로 많은 도움이 될 수 있습니다.
수퍼 클래스 또는 인터페이스의 메서드를 재정의한다고 생각 될 때마다 사용하십시오. 그렇게하면 잘못된 방법으로 컴파일 오류가 발생합니다.
답변
일식을 사용하는 경우 상단 메뉴로 이동하십시오.
소스-> equals () 및 hashCode () 생성
답변
귀하의 질문에 약간의 주제가 없지만 어쨌든 언급 할 가치가 있습니다.
Commons Lang 은 equals와 hashcode를 재정의하는 데 사용할 수있는 훌륭한 방법을 가지고 있습니다. 체크 아웃 EqualsBuilder.reflectionEquals (…) 와 HashCodeBuilder.reflectionHashCode (…) . 과거에 많은 두통을 피했습니다. 물론 ID에서 “동일”을 원한다면 상황에 맞지 않을 수 있습니다.
또한 @Override
equals (또는 다른 방법)를 재정의 할 때마다 주석 을 사용해야한다는 것에 동의합니다 .
답변
상용구 코드를 저장하는 또 다른 빠른 솔루션은 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;
등호에 사용할 필드를 사용자 정의하려면 사용 가능한 옵션을 참조하십시오 . 롬복은 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))
첫 번째 equals가 true이고 object2가 obj1이 속한 클래스의 하위 클래스 인스턴스 인 경우 두 번째 equals는 false를 반환합니다!
ob1이 속하는 것으로 간주되는 클래스가 final로 선언되면이 문제는 발생할 수 없지만 일반적으로 다음과 같이 테스트해야합니다.
this.getClass() != otherObject.getClass();
그렇지 않으면 false를 반환하고 그렇지 않으면 필드를 테스트하여 동등성을 비교하십시오!