带有List <>方法的Java通用接口上的编译器错误

Mar*_*lme 13 java generics collections compiler-errors interface

我不明白以下代码导致的编译器错误.我定义了一个通用接口,参见Task,有两种方法:U doSomething(String value)List<Integer> getIDs().doSomething()方法实际上使用泛型类型作为其返回值的类型,但似乎不会导致问题.该getIDs()方法返回一个List,它与Task的类型无关,但在使用for..each语句迭代返回值时会导致问题.发生以下编译器错误.

error: incompatible types
    for (Integer value : task.getIDs()){
required: Integer
found:    Object
Run Code Online (Sandbox Code Playgroud)

似乎接口上的类型擦除导致编译器忘记第二个方法上的声明类型,这与泛型类型无关.或者换句话说,为什么接口上的泛型类型会影响编译器如何理解方法的返回值getIDs(),特别是在for..each语句的上下文中?

显然,如果我引用for..each之外的列表没有问题,但不是直接的.

public class InterfaceTest {
   public static void main(String[] args) {
      Task task = new MyTask();
      // no complaints about the type here     
      List<Integer> values = task.getIDs();

      // getting a compiler error for this line
      for (Integer value : task.getIDs()){

      }
   }
}


interface Task<U>{
   U doSomething(String value);
   List<Integer> getIDs();
}
Run Code Online (Sandbox Code Playgroud)

接口的实现不是必要的,以证明这一点,但我不想留下参考Task task = null;,并回答告诉我这是问题.

class MyTask implements Task<Boolean>{

   @Override
   public Boolean doSomething(String value) {
      System.out.println(value);
      return false;
   }

   @Override
   public List<Integer> getIDs() {
      return Arrays.asList( 1, 2, 3, 4 );
   }
}
Run Code Online (Sandbox Code Playgroud)

Cra*_*aig 8

发生的事情是当使用带有泛型参数的类(或接口)<T>但是引用和不带的实例<T>(即那种raw类型)时,编译器会从类中删除所有泛型类型信息.这可能是由于与1.5之前的源代码的兼容性,您根本无法使用泛型类型信息.

考虑您在Java 1.4编译器上编写代码和编译的情况.您想使用一个使用泛型的库.当您从该库中引用具有泛型参数作为原始类型的类型时,编译器会强制使用不使用泛型参数.

编辑:

JLS-4.8-210提到了这一点:提到(来源:忠J-宇):

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

这仍然感觉像是一个陷阱,但它可能是出于某种原因.