ジェネリックでのランタイム型チェックの2つのオプション:
オプション1-コンストラクターを破損する
indexOf(...)をオーバーライドしていて、パフォーマンスのためだけに型をチェックして、コレクション全体を繰り返し処理する手間を省こうとしているとします。
次のような不潔なコンストラクタを作成します。
public MyCollection<T>(Class<T> t) {
this.t = t;
}
次に、isAssignableFromを使用してタイプを確認できます。
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
オブジェクトをインスタンス化するたびに、自分自身を繰り返す必要があります。
new MyCollection<Apples>(Apples.class);
あなたはそれが価値がないと決めるかもしれません。ArrayList.indexOf(...)の実装では、型が一致することを確認しません。
オプション2-失敗させる
不明なタイプを必要とする抽象メソッドを使用する必要がある場合、本当に必要なのは、コンパイラーがinstanceofについて叫ぶのをやめることだけです。このようなメソッドがある場合:
protected abstract void abstractMethod(T element);
次のように使用できます。
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
コンパイラをだますために、オブジェクトをT(ジェネリック型)にキャストしています。キャストは実行時に何も行いませんが、間違ったタイプのオブジェクトを抽象メソッドに渡そうとすると、ClassCastExceptionが発生します。
注1:抽象メソッドで追加のチェックされていないキャストを実行している場合、ClassCastExceptionsがここでキャッチされます。それは良いことも悪いこともあるので、よく考えてください。
注2:instanceofを使用すると、無料のnullチェックを取得します。使用できないため、素手でnullを確認する必要があるかもしれません。
Class.isAssignableFrom
。