有人可以向我解释以下行为吗?
我有一个列表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() { ListlistX = new ArrayList<>(); listX.addAll(getA()); listX.addAll(getI()); for (X x : listX) {} } public List getA() { return new ArrayList<>(); } public List getI() { return new ArrayList<>(); }
我错过了什么吗?我不应该两次都得到编译错误吗?
对于Java 8来说,这种行为似乎是新的,下面的版本我在这两种情况下都遇到了编译器错误.
我想简化问题,Shmosel的答案如下:
interface I {} class A implements I {} class X {} public void test() { X temp = getI(); // compiles X temp2 = getA(); // does not compile } publicT getI() { return null; } public T getA() { return null; }
getI()可以返回扩展X并实现I的东西,这就是它编译的原因.通常,它实际返回的类型取决于某些东西,例如传递给函数的参数.
getA()不能返回一个X的东西,因为它返回一个扩展A的东西,它不会扩展X.
listX.addAll(getA());
不编译,因为没有可能的子类也是X
它的子类A
.
listX.addAll(getI());
编译,因为可能有一个子类X
也实现I
.