1

问候。这是我在这个网站上的第一篇文章。

我认为由于type erasure,人们不能期望下面的代码能够编译,事实上,它没有在早期版本的 Eclipse 上编译。我的理解是instanceof是一个运行时运算符,并且不知道泛型类型将在运行时编译掉:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E e)
   {
      if ( !(e instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }

但是,我很惊讶地看到您的一个线程实际上在答案中包含了一些类似这样的代码,而我最新的 Eclipse(Windows 上的 Galileo 与 JVM 1.6 rev 20)对此非常满意——而且它也可以工作。(我确实注意到有人说它在 Eclipse 上工作,但在该线程中的另一个 IDE/JDK 中没有,但不记得具体细节。)

有人可以解释它为什么起作用,更重要的是,因为我必须指导我的学生,是否应该期望它在未来起作用。

谢谢你。(我希望代码格式正确 - 从我的角度来看,它看起来正确缩进并且没有标签。)

4

3 回答 3

4

被抹去的是E. 事实上,你不能这样做if (e instanceof E),因为类型参数E被删除了。但是,String它不是参数化类型,并且e确实具有运行时类型,因此if (e instanceof String)可以正常工作。

JLS 15.20.2 类型instanceof比较运算符

RelationalExpression:
    RelationalExpression instanceof ReferenceType

RelationalExpression运算符的操作数的类型instanceof必须是引用类型或null类型;否则,会发生编译时错误。ReferenceType运算符后面提到的必须instanceof表示引用类型;否则,会发生编译时错误。如果在运算符 ReferenceType 后面提到的 instanceof 不表示可具体化的类型(第 4.7 节),则会出现编译时错误。

String是可具体化的类型。E不是。

JLS 4.7 可具体化类型

由于某些类型信息在编译过程中会被删除,因此并非所有类型在运行时都可用。在运行时完全可用的类型称为可具体化类型。当且仅当满足以下条件之一时,类型才是可具体化的:

  • 它指的是非泛型类型声明。
  • 它是一种参数化类型,其中所有类型参数都是无界通配符
  • 它是原始类型。
  • 它是一种原始类型。
  • 它是一个数组类型,其组件类型是可具体化的。

也可以看看

于 2010-05-08T03:05:40.397 回答
3

这很好用。采用的方法E e编译为Comparable e,但这不会阻止检查运行时存在的类型(String在您的示例中)。您不能做的是检查类似ArrayList<String>(或您自己的类的通用特化)之类的东西,因为该ArrayList类型在运行时存在,但ArrayList<String>不存在。因此,人们使用诸如检查列表的第一个元素之类的技巧。

于 2010-05-08T02:53:44.230 回答
2

小写的 e 是一个对象,每个对象都有它的类型。您可以在任何对象上检查 instanceof。用不同的名字阅读你的代码,它会更容易得到:

   public static <E extends Comparable<? super E>> 
   void SampleForQuestion(E paramObject)
   {
      if ( !(paramObject instanceof String) )
         System.out.println("I am not a String");
      else
         System.out.println("I am  a String");
   }
于 2010-05-08T03:55:36.240 回答