有人可以向我解释以下行为吗?
我有一个X
列表,并使用addAll()
方法添加元素。这些元素由使用泛型类型的方法返回。方法getA()
返回< T extends A >
,其中A
是一个类。方法getI()
返回< T extends I >
,其中I
是一个接口(请参阅下面的代码)。
差异:使用listX.addAll(getA())
我收到编译错误(正如预期的那样),但是listX.addAll(getI())
编译(当元素转换为X
时抛出运行时错误。)
简化代码:
interface I {}
class A implements I {}
class X {}
public void test() {
List<X> listX = new ArrayList<>();
listX.addAll(getA());
listX.addAll(getI());
for (X x : listX) {}
}
public <T extends A> List<T> getA() {
return new ArrayList<>();
}
public <T extends I> List<T> getI() {
return new ArrayList<>();
}
我错过了什么吗?我不应该两次都遇到编译错误吗?
对于Java 8来说,这种行为似乎是新的,下面的版本我在这两种情况下都遇到了编译器错误。
答案 0 :(得分:8)
我想简化问题,Shmosel的答案如下:
interface I {}
class A implements I {}
class X {}
public void test() {
X temp = getI(); // compiles
X temp2 = getA(); // does not compile
}
public <T extends I> T getI() {
return null;
}
public <T extends A> T getA() {
return null;
}
getI()可以返回扩展X并实现I的东西,这就是它编译的原因。通常,它实际返回的类型取决于某些东西,例如传递给函数的参数。
getA()不能返回X的内容,因为它返回扩展A的内容,但不会扩展X.
答案 1 :(得分:7)
listX.addAll(getA());
无法编译,因为X
没有可能的子类,它们也是A
的子类。
listX.addAll(getI());
确实编译,因为可能有一个X
的子类也实现了I
。