次のコード:
((tempVar instanceof ArrayList<Foo>) ? tempVar : null);
原因:
パラメーター化された型
ArrayList<Foo>
に対してinstanceof
チェックを実行できません。実行時にさらに一般的な型情報が消去されるため、代わりにArrayList<?>
の形式を使用します
「実行時にさらに一般的な型情報が消去される」とはどういう意味ですか?これを修正する方法はありますか?
つまり、パラメーター化されたものがある場合、たとえばList<Foo> fooList = new ArrayList<Foo>();
、ジェネリック情報は実行時に消去されます。代わりに、これはJVMがList fooList = new ArrayList();
を見るものです。
これは type erasure と呼ばれます。 JVMには、実行時のList
(この例では)のパラメーター化された型情報はありません。
修正? JVMには実行時にパラメータ化された型の情報がないため、instanceof
of ArrayList<Foo>
を実行する方法はありません。パラメータ化された型を明示的に「保存」して、そこで比較を行うことができます。
代わりに常にこれを行うことができます
try
{
if(obj instanceof ArrayList<?>)
{
if(((ArrayList<?>)obj).get(0) instanceof MyObject)
{
// do stuff
}
}
}
catch(NullPointerException e)
{
e.printStackTrace();
}
型の消去により、ArrayList
のパラメーター化された型は実行時に認識されません。 instanceof
でできる最善の方法は、tempVar
が(何でも)ArrayList
であるかどうかを確認することです。ジェネリックフレンドリーな方法でこれを行うには、次を使用します。
((tempVar instanceof ArrayList<?>) ? tempVar : null);
これで十分です。
if(obj instanceof ArrayList<?>)
{
if(((ArrayList<?>)obj).get(0) instanceof MyObject)
{
// do stuff
}
}
実際、instanceof
は、左のオペランドがnull
であるかどうかを確認し、実際にfalse
である場合はnull
を返します。
そのため、NullPointerException
をキャッチする必要はありません。
それを修正することはできません。 Genericsの型情報は実行時に利用できず、アクセスできません。配列の内容のみを確認できます。
instanceof演算子は実行時に機能します。ただし、Javaは、実行時にパラメータ化された型情報を保持しません。コンパイル時に消去されます。したがって、エラーが発生します。
使用できます
boolean isInstanceArrayList = tempVar.getClass() == ArrayList.class
これはいつでもできる
クラスを作成する
public class ListFoo {
private List<Foo> theList;
public ListFoo(List<Foo> theList {
this.theList = theLista;
}
public List<Foo> getList() {
return theList;
}
}
同じではありませんが...
myList = new ArrayList<Foo>;
.....
Object tempVar = new ListFoo(myList);
....
((tempVar instanceof ListFoo) ? tempVar.getList() : null);