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

以下代码:

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

原因:

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

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

【问题讨论】:

    标签: java android generics


    【解决方案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
              

              【讨论】:

                猜你喜欢
                • 2017-11-29
                • 2018-02-10
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多