Eli*_*nko 15 java generics compiler-errors wildcard
给出以下两个类定义:
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>,似乎没有解决方案可以通过与上述相同的推理得出.
Maurizio 在 compiler-dev 上的回应最好地回答了这个问题。
(TL;DR javac 确实与此处的规范不一致,最佳解决方案可能位于两种方法之间)
可以在此处找到相关的错误。
非常感谢所有对此答案做出贡献的人。