java equals()メソッドのオーバーライド-動作していませんか?

StackOverflow https://stackoverflow.com/questions/185937

  •  06-07-2019
  •  | 
  •  

質問

今日、 equals()メソッドで興味深い(非常にイライラする)問題が発生しました。これにより、十分にテストされたクラスと思われるものがクラッシュし、バグが発生しました。追跡に時間がかかります。

完全を期すために、私はIDEやデバッガーを使用していませんでした。古き良き時代のテキストエディターとSystem.outだけです。時間は非常に限られており、学校のプロジェクトでした。

とにかく-

Book オブジェクトの ArrayList を含むことができる基本的なショッピングカートを開発していました。カートの addBook() removeBook()、および hasBook()メソッドを実装するために、< code> Book は既に Cart に存在していました。じゃあ行って-

public boolean equals(Book b) {
    ... // More code here - null checks
    if (b.getID() == this.getID()) return true;
    else return false;
}

テストではすべて正常に動作します。 6つのオブジェクトを作成し、それらにデータを入力します。 Cart で多くの追加、削除、has()操作を行うと、すべてが正常に機能します。 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 オブジェクトだったにもかかわらず、Bookパラメーターを使用しないことに決めた理由はありますか?唯一の違いは、同じクラス内からインスタンス化され、1つのデータメンバーのみで満たされているように思われます。私はとても混乱しています。光を当ててください。

役に立ちましたか?

解決

Javaでは、 Object から継承される equals()メソッドは次のとおりです。

public boolean equals(Object other);

つまり、パラメーターは Object 型でなければなりません。

ArrayList は正しいequalsメソッドを使用します。このメソッドでは、 Object のequalsを適切にオーバーライドしなかったメソッドを常に呼び出していました。

メソッドを正しくオーバーライドしないと、問題が発生する可能性があります。

毎回次の値と等しいオーバーライド:

@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を使用する場合は、トップメニューに移動してください

  

出典-&gt; equals()を生成し、   hashCode()

あなたの質問から少し外れていますが、とにかく言及する価値があるでしょう:

Commons Lang には、equalsとhashcodeのオーバーライドに使用できるいくつかの優れたメソッドがあります。 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は maven で利用できます。 提供スコープで追加するだけです:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.14.8</version>
    <scope>provided</scope>
</dependency>

Android Studioでは alt + insert ---&gt;等しいおよび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 ステートメントは、equalsの実装でよく使用されます。

これはよくある落とし穴です!

問題は、 instanceOf を使用すると対称性の規則に違反することです。

(object1.equals(object2)== true) 次の場合にのみ (object2.equals(object1))

最初の等号が真であり、object2がサブクラスのインスタンスである場合 obj1が属するクラスの場合、2番目のequalsはfalseを返します!

ob1が属するとみなされるクラスがfinalとして宣言されている場合、これ 問題は発生しませんが、一般に、次のようにテストする必要があります。

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;
    }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top