问候。这是我在这个网站上的第一篇文章。
我认为由于 类型擦除 ,人们不能指望编译以下代码,事实上,它不能在早期版本的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中没有,但是不记得具体细节。)
有人可以解释它为什么有效,更重要的是,因为我必须引导我的学生,是否应该预期它将来有用。
谢谢。 (我希望代码格式化正确 - 从我的角度来看它看起来是正确缩进的,并且没有标签。)
答案 0 :(得分:4)
删除的内容是E
。事实上,您不能if (e instanceof E)
,因为类型参数E
已被删除。但是,String
不是参数化类型,而e
确实具有运行时类型,因此if (e instanceof String)
工作正常。
instanceof
operator RelationalExpression: RelationalExpression instanceof ReferenceType
RelationalExpression
运算符的instanceof
操作数的类型必须是引用类型或null
类型;否则,发生编译时错误。ReferenceType
运算符后面提到的instanceof
必须表示引用类型;否则,发生编译时错误。 如果在ReferenceType
运算符后面提到的instanceof
不表示可再生类型,则为编译时错误(§4.7)。
String
是一种可重复的类型。 E
不是。
由于在编译期间会删除某些类型信息,因此并非所有类型在运行时都可用。在运行时完全可用的类型称为可重新类型。当且仅当下列之一成立时,类型才可以恢复:
- 它指的是非泛型类型声明。
- 这是一个参数化类型,其中所有类型参数都是无界通配符
- 这是一种原始类型。
- 这是一种原始类型。
- 这是一种数组类型,其组件类型可以恢复。
instanceof
和.class
字面值是可以使用新代码中的原始类型的两个例外答案 1 :(得分:3)
工作正常。将E e
的方法编译为Comparable e
,但这不会阻止对运行时存在的类型(在您的示例中为String
)进行检查。您不能做的是检查类似ArrayList<String>
(或您自己类的通用特化)的内容,因为ArrayList
类型在运行时存在,但ArrayList<String>
不存在。因此,人们使用黑客来检查列表的第一个元素。
答案 2 :(得分: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");
}