Java 6TreeSet<E>
ドキュメントから:
boolean remove(Object o):
Removes the specified element from this set if it is present.
ジェネリック型 E ではなくオブジェクトを受け入れるのはなぜですか? 追加できるオブジェクトはタイプ E のみであるため、取り外し可能なタイプはタイプ E のみにする必要があります。
Java 6TreeSet<E>
ドキュメントから:
boolean remove(Object o):
Removes the specified element from this set if it is present.
ジェネリック型 E ではなくオブジェクトを受け入れるのはなぜですか? 追加できるオブジェクトはタイプ E のみであるため、取り外し可能なタイプはタイプ E のみにする必要があります。
投稿された最初のコメントから答えを得る:
神話:
愚かで邪悪だというのが一般的な神話ですが、下位互換性のために必要でした。しかし、互換性の議論は関係ありません。互換性を考慮するかどうかにかかわらず、API は正しいものです。
本当の理由:
一様に、Java Collections Framework (および Google Collections Library も) のメソッドは、コレクションが壊れないようにする必要がある場合を除いて、パラメーターの型を制限することはありません。
remove()
、 likeは、 ( に関して)等しいget()
要素が与えられたときに機能する必要があります。Java では、異なるクラスのオブジェクトが同等であることが可能です (場合によっては必須です)。したがって、タイプを制限するべきではありません。.equals()
各 E もオブジェクトであり、おそらく現時点では (たとえばイベント ソースからの) E を E として持っていないため、便利です。それ以外の場合は、それを削除するためだけに E にキャストする必要があります。
等価性の観点からは、これは問題ではありません。指定されたオブジェクトの参照アドレスがセットの内容と等しいかどうかがテストされるため、それがどのクラスであるかは問題ではありません。
これは確かに問題です。誰かが を呼び出しremove(o)
てo
の型が でないE
場合、通常は間違ったものを取り除こうとするプログラミングのバグです。型チェックはバグから私たちを守ることができませんでした.
優れた IDE (IntelliJ) はそのような問題を検出して警告することができますが、API 設計者は、コンパイラの型チェックを利用するために、より正確な署名を提供する必要がありました。(IDE はここでチートを行いSet.remove()
ます。これは標準 API であるため、意味を認識しています。IDE は、カスタム API に対して同じヘルプを提供しません)
のようなクエリ API の場合contains()
、非引数を受け入れてE
単純な false を返すことは問題ありません。だから私たちは両方を持つことができます
boolean contains(Object o);
boolean contains2(E o);
のようなミューテーション APIの場合、非引数remove()
を受け入れるかどうかは議論の余地があります。E
しかし、消去の現実を考えると、議論は無意味なものになるでしょう - 非 E の議論を受け入れ、それについて沈黙する以外に選択肢はありません。それでも、2 つの方法を使用できます
boolean remove(Object o);
boolean remove2(E o);
ほとんどの場合、プログラマーはcontains2/remove2
追加のタイプ セーフを呼び出すことができます。