java - java中未指定泛型和<?>之间的编译差异

标签 java generics

我觉得这完全令人困惑。由于某种原因,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/

相关文章:

java - 从通用管理器类中,如何以静态方式访问有关其实例的信息?

java - 备用java语言

java - JSON-lib 转义/保留字符串

java - 自动生成非泛型接口(interface)实现

java - JAXB 泛型 @XmlValue

c# - 如何在 C# 中对开放类型进行泛型多态?

java - 如何在 Eclipse 上使用我的 java 类文件更新外部 jar

java - 如何查找给定时间戳是否在 cron 表达式内?

java - 使用堆栈检查分隔符

java - 将 ArrayList<> 对象传递给扩展 ArrayList 的类