为什么使用原始类型变量会影响签名而不引用类型参数?

Why does using raw type variables affect signatures without reference to type-parameters?

查看另一个 question 我遇到了 1.8 的这种有趣行为。0_112 Sun-Oracle 编译器(我没有与其他人一起测试):

import java.util.List;

interface Alpha<T> {
   List<Integer> intList();
}

interface Beta {
   List<Integer> intList();
}

class Main {

   public static void main(String[] args) {

      Alpha rawAlpha = null;
      Alpha<Character> charAlpha = null;
      Alpha<?> qmAlpha = null;
      Beta beta = null;

      for (Integer i : charAlpha.intList()) {}
      for (Integer i : qmAlpha.intList()) {}
      for (Integer i : beta.intList()) {}
      for (Integer i : rawAlpha.intList()) {}
   }
}

编译器在最后一个for循环失败:

error: incompatible types: Object cannot be converted to Integer
      for (Integer i : rawAlpha.intList()) {}
                                       ^
1 error

所以尽管 intList() return Alpha 中的列表类型 List<Integer> 不依赖于类型参数 T,但 <Integer> 在编译时被擦除。

请注意,如果我们声明一个非通用接口 Beta,从理论上讲,这相当于引用原始 Alpha,没有问题。

这是预期的行为吗?有人可以指出涵盖这一点的语言规范的段落吗?如果这至少不是一个错误,它看起来相当反直觉和非生产性;也许是为了回溯比较?

说这个(有点不清楚)的 JLS 位在 JLS 4.8:

The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) 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.

因此,由于 rawAlpha 是原始类型,因此 rawAlpha.intList 的类型是 List<Integer> intList() 的擦除。擦除是 List intList().

至于为什么,我手头没有引文,但原始类型只是为了向后兼容才真正出现在 Java 中。这意味着它们只需要像使用泛型之前那样工作即可;您所要求的是比以前工作得更好一点的代码。这不是不合理,但这不是他们决定的。 :-)