[java] java equals () 메소드 재정의-작동하지 않습니까?

나는 equals()오늘 시험 법 에 대한 흥미롭고 매우 실망스러운 문제 에 부딪쳤다.

완벽 함을 위해 IDE 또는 디버거를 사용하지 않았습니다. 좋은 구식 텍스트 편집기와 System.out입니다. 시간은 매우 제한되어 있었고 학교 프로젝트였습니다.

어쨌든-

나는 포함 할 수있는 기본적인 쇼핑 카트를 개발하고 ArrayListBook객체 . 구현하기 위해 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(), 방법) 하지 과부하 사람. 대부분의 코드에서 Objectequals를 올바르게 재정의하지 않은 코드를 호출하는 것은 좋지만와 호환되지 않습니다 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에서 “동일”을 원한다면 상황에 맞지 않을 수 있습니다.

또한 @Overrideequals (또는 다른 방법)를 재정의 할 때마다 주석 을 사용해야한다는 것에 동의합니다 .


답변

상용구 코드를 저장하는 또 다른 빠른 솔루션은 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를 반환하고 그렇지 않으면 필드를 테스트하여 동등성을 비교하십시오!