我一直在打击这个问题一段时间,并认为可能会有一些新鲜的眼睛看到这个问题; 谢谢你的时间.
import java.util.*;
class Tbin<T> extends ArrayList<T> {}
class TbinList<T> extends ArrayList<Tbin<T>> {}
class Base {}
class Derived extends Base {}
public class Test {
public static void main(String[] args) {
ArrayList<Tbin<? extends Base>> test = new ArrayList<>();
test.add(new Tbin<Derived>());
TbinList<? extends Base> test2 = new TbinList<>();
test2.add(new Tbin<Derived>());
}
}
Run Code Online (Sandbox Code Playgroud)
使用Java 8.在我看来,直接创建容器test
就等同于容器test2
,但编译器说:
Test.java:15: error: no suitable method found for add(Tbin<Derived>)
test2.add(new Tbin<Derived>());
^
Run Code Online (Sandbox Code Playgroud)
我怎么写Tbin
,TbinList
所以最后一行是可以接受的?
请注意,我实际上将添加类型Tbin
s,这就是我Tbin<Derived>
在最后一行中指定的原因.
给出以下两个类定义:
class C1<T extends C1<T>> {}
class C2<U> extends C1<C2<U>> {}
Run Code Online (Sandbox Code Playgroud)
请考虑以下类型声明:
C1<? extends C2<String>> c;
Run Code Online (Sandbox Code Playgroud)
这将编译在JDK-8u45好的,但如果我们考察了采集转换规范,它出现(我)这个声明应该导致编译时错误.
特别是,新类型变量捕获的上限由下式T#1
给出glb(Bi, Ui[A1:=S1,...,An:=Sn])
,在这种情况下,Bi
解析为通配符绑定C2<String>
并Ui[A1:=S1,...,An:=Sn]
解析为C1<T#1>
.
由此,glb(C2<?>, C1<T#1>)
解析为交叉点型C2<String> & C1<T#1>
,这是无效的,因为C2<String>
和C1<T#1>
都是类类型,而不是接口类型,但其中没有一个是另一个的子类型.
我确定这不是一个错误,我只是在某个地方犯了一些简单的错误...... 如果它是一个bug,我希望它可以被认为是JLS中的错误而不是JDK,这样我可以期望能够安全地模拟行为......
谢谢你的帮助!
编辑:有Radiodef昨天交谈后我说服自己,这个问题(或者看它单程至少)是C2<String>
能有效地被认为是作为一个亚型C1<T#1>
,因为T#1只能永远被满足C2<String>
,因此可被认为是相同的,但是遏制和子类型规则并没有像写的那样理解这种关系,因此JLS不会识别子类型并且应该失败......
但是,如果你采取稍微复杂的情况C1<? extends C2<?>> d;
,那就更棘手了.问题是类似的,但是形成捕获上限的交集类型出现了C2<?> & C1<T#2>
,似乎没有解决方案可以通过与上述相同的推理得出.