带有 List<> 的 Java 通用接口上的编译器错误方法 [英] Compiler error on Java generic interface with a List<> method

查看:18
本文介绍了带有 List<> 的 Java 通用接口上的编译器错误方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

错误:类型不兼容for (整数值:task.getIDs()){要求:整数找到:对象

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

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

public class InterfaceTest {公共静态无效主(字符串 [] args){任务 task = new MyTask();//这里没有关于类型的抱怨列表<整数>值 = task.getIDs();//得到这一行的编译器错误for (整数值:task.getIDs()){}}}接口任务{你做某事(字符串值);列表<整数>getIDs();}

<小时>

接口的实现不需要证明这一点,但我不想留下参考 Task task = null; 并且有答案告诉我这就是问题所在.>

class MyTask 实现 Task{@覆盖公共布尔 doSomething(字符串值){System.out.println(value);返回假;}@覆盖公共列表<整数>getIDs() {返回 Arrays.asList( 1, 2, 3, 4 );}}

解决方案

当使用一个类(或接口)和一个泛型参数 但引用和实例时会发生什么对于没有 (即 raw 类型)的情况,编译器会从类中删除所有泛型类型信息.这可能是因为与 1.5 之前的源代码兼容,您根本无法使用泛型类型信息.

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

JLS-4.8-210 提到这一点时暗示了这一点(来源:zhong-j-yu):

<块引用>

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

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

I don't understand the compiler error resulting from the following code. I define a generic interface, see Task, with two methods: U doSomething(String value) and List<Integer> getIDs(). The doSomething() method actually uses the generic type as the type of its return value, but doesn't seem to be causing problems. The getIDs() method returns a List, which is unrelated to the type of Task, but it is causing problems when using for..each statement to iterate over the return value. The following compiler error occurs.

error: incompatible types
    for (Integer value : task.getIDs()){
required: Integer
found:    Object

It seems that the type erasure on the interface is causing the compiler to forget the declared type on the second method, which is unrelated to the generic type. Or in other words why is the generic type on the interface affecting how the compiler understands the return value on the getIDs() method and specifically in the context of a for..each statement?

Apparently if I get reference to the list outside of the for..each there is no problem, but not directly.

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();
}


The implementation of the interface isn't necessary to demonstrate the point, but I didn't want to leave the reference Task task = null; and have answer's telling me that's the problem.

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 );
   }
}

解决方案

What is happening is when use use a class (or interface) with a generic parameter <T> but refer to and instance of the without <T> (ie. that raw type) the compiler erases all generic type information from the class. This is likely due to compatibility with pre-1.5 source code where you wouldn't be able to use generic type information at all.

Consider the situation where you are writing code and compiling on a Java 1.4 compiler. You want to use a library which makes use of generics. When you refer to a type from that library which has generic parameters as a raw type, the compiler enforces the use of no generic parameters.

EDIT:

The JLS-4.8-210 alludes to this when it mentions (credit: zhong-j-yu):

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.

This still feels like a gotcha, but it is likely for some reason.

这篇关于带有 List&lt;&gt; 的 Java 通用接口上的编译器错误方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆