11

查看另一个问题,我遇到了 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()返回列表类型不依赖于类型参数List<Integer>,但似乎在编译时被删除了。AlphaT<Integer>

Beta请注意,如果我们声明一个在理论上相当于引用 raw的非泛型接口,Alpha则没有问题。

这是预期的行为吗?有人可以指出语言规范中涵盖这一点的段落吗?如果这至少不是一个错误,那么它似乎相当反直觉和非生产性;也许是为了向后可比性而完成的?

4

1 回答 1

12

说明这一点的 JLS 位(有点不清楚)在JLS 4.8中:

未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或非静态字段(第 8.3 节)的类型是对应于的原始类型在对应于 C 的泛型声明中擦除其类型。

所以,既然rawAlpha是原始类型,那么 的类型rawAlpha.intList就是 的擦除List<Integer> intList()。那个擦除是List intList()

至于为什么,我没有方便的引用,但原始类型仅在 Java 中用于向后兼容。这意味着它们只需要像在泛型之前那样工作;你所要求的是代码比以前好一点。这不是不合理,但这不是他们决定的。:-)

于 2017-03-28T18:14:33.070 回答