我觉得这完全令人困惑。由于某种原因,javac 似乎会处理带有未指定泛型的引用和 <?>
在类型安全方面有所不同。有谁知道这是为什么(Java 1.6)?
public abstract class ClassWithGenericMember<GenMember> {
GenMember getMember() {
return (GenMember) null;
}
<GenReturn> GenReturn handle(Handler<GenReturn> handler) {
return handler.handle();
}
interface Handler<GenHandled> {
public GenHandled handle();
}
static class ClassWithMember extends ClassWithGenericMember<MemberType> {
}
static class MemberType {
}
static class HandledType {
}
public static void main(String[] argv) {
HandledType handled = null;
Handler<HandledType> handler = new Handler<HandledType>(){
public HandledType handle() {
return (HandledType) null;
}
};
ClassWithMember concrete = new ClassWithMember();
ClassWithGenericMember<?> bracket = concrete;
ClassWithGenericMember noBracket = concrete;
handled = concrete.handle(handler); //compiles
handled = bracket.handle(handler); //compiles
handled = noBracket.handle(handler); //fails:
/*
ClassWithGenericMember.java:38: incompatible types
found : java.lang.Object
required: ClassWithGenericMember.HandledType
handled = noBracket.handle(handler);
^
Note: ClassWithGenericMember.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
*/
}
}
最佳答案
尽管看起来很奇怪,但当您使用原始类型时,所有泛型类型(所有,而不仅仅是类的参数化类型)都会从类内的声明中删除(JLS 4.8):
The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C.
当您使用ClassWithGenericMember noBracket
(“原始类型C”)时,noBracket.handle()
的类型是“对应于删除的原始类型”它的类型”,即对象句柄(HandlerType handler)
。 (正如您在评论中所说)“调用不以任何方式使用类的通用成员类型”并不重要。
请注意,这仅适用于直接在类中声明的构造函数、实例方法和非静态字段的类型(例如,不适用于类方法、静态字段、继承方法),并且不会影响实现的声明(例如方法中的声明)。
--
这个问题/答案已经出现过几次了,比如:
关于java - java中未指定泛型和<?>之间的编译差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16576510/