小编Eli*_*nko的帖子

捕获Java中的转换问题,JLS的WRT协调和实际的JDK行为

给出以下两个类定义:

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>,似乎没有解决方案可以通过与上述相同的推理得出.

java generics compiler-errors wildcard

15
推荐指数
1
解决办法
329
查看次数

可能的Java编译器错误!程序不能与某些编译器一起编译

首先,一点背景(如果不感兴趣,可以跳过一点).我很生气,很困惑!这应该是一个非常简单的用例,事实上我的代码已经用Eclipse JDT编译器编译得很好,所以直到现在我一直在配置Maven以确保这样做.尽管它不能用Oracle JDK和OpenJDK编译,但是我一直在困扰我,因为我认为它可能实际上是我的代码的问题,所以我再次研究它.

我想也许这个bug是在JDT编译器中允许它编译的,而不是Oracle JDK和OpenJDK因为不允许它,我也用它来测试这两个.有问题的原始代码要复杂得多,所以我很难看到问题出在哪里,事实上,我很惊讶地发现在不编译的情况下可以减少这个问题的程度.

Eclipse JDT编译器或Oracle JDK和OpenJDK都有一个非常重要的(imho)错误.

TL; DR

这是相关代码的相当小的表示.(Anything的类型绑定可以被任何接口替换,编译器行为不会改变):

public class Bug<X extends Property<?, ?> & Anything> {
}

interface Property<C, S extends C> extends PropertyConst<C> {
    @Override
    public S get();
}

interface PropertyConst<C> {
    public C get();
}

interface Anything {
}
Run Code Online (Sandbox Code Playgroud)

总而言之,我认为这应该编译得很好,但Oracle JDK 7&8和OpenJDK 7不同意.它使用Eclipse Juno为我编译.

当使用这些编译器中的任何一个编译时,上面的代码给出类似于以下错误的东西,但是对于JDT编译器工作得很好:

Bug.java:3: error: types PropertyConst<?> and Property<?,?> are incompatible; both define get(), but with unrelated return types
public class Bug<X extends Property<?, ?> & Anything> {
                 ^
1 …
Run Code Online (Sandbox Code Playgroud)

java generics openjdk compiler-bug eclipse-jdt

5
推荐指数
1
解决办法
1137
查看次数

Java中的参数化良好形式和捕获转换

给出以下两个类定义:

class C1<T extends C1<T>> {}

class C2<U> extends C1<C2<U>> {}
Run Code Online (Sandbox Code Playgroud)

以下类型声明:

C1<C2<?>> a;
Run Code Online (Sandbox Code Playgroud)

直观地认为声明的类型a应该是有效的,但这不是JDK-8u45的行为方式.相反,我们得到类似以下输出:

Test.java:3: error: type argument C2<?> is not within bounds of type-variable T
        C1<C2<?>> a;
             ^
  where T is a type-variable:
    T extends C1<T> declared in class C1
1 error
Run Code Online (Sandbox Code Playgroud)

(编辑:我在这里是一个dingus,这部分已经回答:C2<?> 没有延伸C1<C2<?>>.关于c下面声明的问题仍然是一个悬而未决的问题.)

但是C2<?> 确实延伸了C1<C2<?>>,这似乎很容易满足界限.到目前为止,对JLS的检查没有提供进一步的照明.它实际上应该只是满足子类型关系的约束,因为C2<?>它不是通配符类型,因此捕获转换只是对参数的标识转换.

在某些情况下,它变得不那么清晰,例如,采用以下类定义:

class C3<T extends C3<?>> {}

class C4<Y, Z> extends C3<C4<Z, Y>> {}

class …
Run Code Online (Sandbox Code Playgroud)

java generics compiler-errors wildcard java-8

5
推荐指数
1
解决办法
87
查看次数