无法对参数化类型 ArrayList<Foo> 执行 instanceof 检查

Posted

技术标签:

【中文标题】无法对参数化类型 ArrayList<Foo> 执行 instanceof 检查【英文标题】:Cannot perform instanceof check against parameterized type ArrayList<Foo> 【发布时间】:2011-09-07 13:51:39 【问题描述】:

以下代码:

((tempVar instanceof ArrayList<Foo>) ? tempVar : null);

原因:

无法针对参数化类型ArrayList&lt;Foo&gt; 执行instanceof 检查。请改用ArrayList&lt;?&gt; 形式,因为更多的泛型类型信息将在运行时被删除

谁能解释一下“更多的泛型类型信息将在运行时被删除”是什么意思以及如何解决这个问题?

【问题讨论】:

【参考方案1】:

这意味着如果你有任何参数化的东西,例如List&lt;Foo&gt; fooList = new ArrayList&lt;Foo&gt;();,泛型信息将在运行时被删除。相反,这是 JVM 将看到的 List fooList = new ArrayList();

这称为type erasure。 JVM在运行时没有List(示例中)的参数化类型信息。

修复?由于 JVM 在运行时没有参数化类型的信息,因此您无法执行 instanceofArrayList&lt;Foo&gt;。您可以显式“存储”参数化类型并在那里进行比较。

【讨论】:

You can "store" the parameterized type explicitly and do a comparison there. 我们可以看看这个例子吗?【参考方案2】:

你总是可以这样做

try

    if(obj instanceof ArrayList<?>)
    
        if(((ArrayList<?>)obj).get(0) instanceof MyObject)
        
            // do stuff
        
    

catch(NullPointerException e)

    e.printStackTrace();

【讨论】:

如果是空的怎么办 @RafaelRuiz 我认为简单的 try/catch 强制转换为正确的类型 ArrayList 就可以了? 如果你知道 Foo 类是 MyObject 类,你可以这样做。【参考方案3】:

由于类型擦除,ArrayList 的参数化类型在运行时将是未知的。使用instanceof 可以做的最好的事情是检查tempVar 是否是ArrayList(任何东西)。要以对泛型友好的方式执行此操作,请使用:

((tempVar instanceof ArrayList<?>) ? tempVar : null);

【讨论】:

【参考方案4】:

这就足够了:

if(obj instanceof ArrayList<?>)

   if(((ArrayList<?>)obj).get(0) instanceof MyObject)
   
       // do stuff
   

其实instanceof检查左操作数是否为null,如果是null则返回false。 所以:没必要抓NullPointerException

【讨论】:

这不是更适合对原始帖子发表评论吗? 不需要捕捉NullPointer,但需要捕捉IndexOutOfBounds【参考方案5】:

instanceof 运算符在运行时工作。但是 java 在运行时不携带参数化的类型信息。它们在编译时被擦除。因此错误。

【讨论】:

【参考方案6】:

你无法解决这个问题。泛型的类型信息在运行时不可用,您将无权访问它。只能查看数组的内容。

【讨论】:

【参考方案7】:

你总是可以这样做

创建一个类

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);

【讨论】:

【参考方案8】:

要执行准确的检查类型而不是这样:

protected <Foo> ArrayList<Foo> myMethod(Object tempVar ) 
    return tempVar instanceof ArrayList<Foo>) ? (ArrayList<Foo>) tempVar : null;

你可以这样做:

protected <Foo> ArrayList<Foo> myMethod(Object tempVar, Class<Foo> clz) 
    if (tempVar instanceof ArrayList && (tempVar.size() == 0 || clz.isInstance(tempVar.get(0))))
        return (ArrayList<Foo>) tempVar;
    return null;

通过这种方式,您的代码是完全安全的。

【讨论】:

【参考方案9】:

你可以使用

boolean isInstanceArrayList = tempVar.getClass() == ArrayList.class

【讨论】:

以上是关于无法对参数化类型 ArrayList<Foo> 执行 instanceof 检查的主要内容,如果未能解决你的问题,请参考以下文章

无法转换“Foo!”类型的值到预期的参数类型'Foo!'

无法对对象类型 ArrayList 实现 Filterable

Java基础Java中如何获取一个类中泛型的实际类型

为什么在实例化模板时必须在参数包中显式显示类型?

Colliction子集(list ,set, Arraylist, Vector.....)

函数模板参数的C++模板实例化