0

私は最近、JDK6 のクラス ProcessBuilder がオーバーライドしないことを発見しましequals()。理由はありますか?クラスはミュータブルなので、なぜオーバーライドしないのか理解できますhashCode()

このコードが機能しないことに驚きました。

ProcessBuilder x = new ProcessBuilder("abc", "def");
ProcessBuilder y = new ProcessBuilder("abc", "def");
if (x.equals(y)) {  // they are never equal
    // something important here
}

クラス の JDK6 ソース コードを調べましたが、 のオーバーライドが見当たりProcessBuilderませんequals()

このクラス以外にも、もっと深い理由がある気がします。おそらくこれは意図的なものでしょうか?

4

2 に答える 2

1

同じオブジェクトでない限り、変更可能なオブジェクトを等しくしないことをお勧めします。これは、オブジェクトが後で変更される可能性があるためです。次のことを考慮してください

Set<ProcessBuilder> pbSet = new HashSet<>();
pbSet.add(x);
pbSet.add(y);
// if x and y were equal pbSet would have one element.
y.setSomething()
// should pbSet have one or two elements.

これよりも悪いのは、2 つのオブジェクトが異なる可能性があるが、後で同じになるという逆のケースです。これは、セットに重複したオブジェクトがあることを意味します。

興味深いのは、コレクションは変更可能ですが、equals と hashCode が含まれていることです。これが当てはまる理由は、不変のコレクションがないためだと思います。たとえば、String オーバーライド equals() ですが、StringBuilder はそうではありません。

于 2013-07-07T16:17:17.387 に答える
1

@PeterLawreyの答えを補完するために:本質的に変更可能なオブジェクトの場合、equalsとハッシュコードを実装することは、いずれにせよ危険です。そのようなオブジェクトが安全に公開されるという保証はまったくありません。したがって、そのようなクラスの作成者が、そのようなクラスの equals とハッシュコードを単に「あきらめた」ことは理にかなっています。

ただし、この平等を制御できると合理的に確信している場合は、Guava'sEquivalence . 高度に変更可能なクラスへの十分に制御されたアクセスを保証できる場合、これにより、そのようなオブジェクトに対して equals/hashcode 戦略を定義できるようになり、たとえばHashSet.

これについての詳細:本質的に変更可能であるが、特定のコンテキストで同等性を保証できるEquivalence「不安定な」クラスの場合、 . 次に、これらのインスタンスをたとえば次のように「ラップ」します。XEquivalence<X>X

Set<Equivalence.Wrapper<X>>

次に、次を使用してこのセットに追加します。

set.add(eq.wrap(x));

eqの実装はどこにありますかEquivalence

于 2013-07-07T16:39:05.193 に答える