1. ホーム
  2. java

[解決済み] javaのequals()メソッドをオーバーライドする - 動作しない?

2022-04-28 12:15:14

質問

について、興味深い(そして非常に苛立たしい)問題に遭遇しました。 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 パラメータを取らないと決めた理由は何ですか? でした。 a Book オブジェクトを作成できますか?唯一の違いは、同じクラス内からインスタンス化され、1つのデータ・メンバーで満たされているように見えました。私は非常に非常に混乱しています。どうか、光を当ててください。

解決方法は?

Javaでは equals() から継承されるメソッドです。 Object があります。

public boolean equals(Object other);

つまり、パラメータは必ず Object . これは オーバーライド ;あなたのメソッド public boolean equals(Book other) と呼ばれるものを行います。 オーバーロード equals() メソッドを使用します。

は、その ArrayList はオーバーライドされた equals() メソッドで内容を比較します(例えば、その contains()equals() メソッド) を使用します。 ない をオーバーロードしたもの。あなたのコードの大部分では、適切にオーバーライドされていないものを呼び出すと Object のequalは問題なかったが、互換性がない。 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 アノテーションを使用することで、間違いを減らすことができます。

スーパークラスやインターフェイスのメソッドをオーバーライドするときは、いつでもこれを使います。そうすれば、もし間違ったやり方をすれば、コンパイルエラーになる。