ジェネリックを使用した実行時の型チェックの 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を確認する必要があるかもしれません。