首先,一些背景知识(如果不感兴趣,请略略略过)。我很生气和困惑!这应该是一个非常简单的用例,实际上我的代码已经用 Eclipse JDT 编译器编译得很好,所以直到现在我一直在配置 Maven 以确保这样做。尽管它不能与 Oracle JDK 和 OpenJDK 一起编译,但它一直困扰着我,因为我认为这实际上可能是我的代码有问题,所以我再次调查了它。
我认为这个错误可能是在 JDT 编译器中允许它编译,而不是 Oracle JDK 和 OpenJDK 不允许它,我也测试过这两者。有问题的原始代码要复杂得多,因此我更难看出问题出在哪里,事实上,我很惊讶地看到在仍未编译的情况下可以将其减少到何种程度。
Eclipse JDT 编译器或 Oracle JDK 和 OpenJDK 都有一个相当大的(恕我直言)错误。
TL;博士
这是有问题的代码的一个相当小的表示。(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 {
}
总而言之,我认为这应该编译得很好,但是 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 error
这是没有意义的。返回类型显然是相关的,因为引用的两种方法之一必然会覆盖另一个。我几乎 99% 相信这应该会起作用,事实上,最后 1% 缺失的唯一原因是泛型的使用太基本了,以至于没有被发现,但我没有发现相关的错误报告给它。(诚然,我并没有努力,因为http://bugs.sun.com/是最糟糕的。你甚至可以通过错误报告是否仍然打开来过滤关键字搜索结果吗?呃。)
对我来说最令人困惑的部分是,当您删除 X 上任何东西的类型边界时,它编译得很好,即使额外的接口与错误无关。
谁能让我放心?任何人都知道为此存在的错误报告,或者以前有过相关经验并且可以告诉我问题是什么?如果我没有得到任何确凿的答案,我会提交一些错误报告。
编辑:
有几个人指出我在使用 <S extends C, C> 时遇到了前向引用错误。不知道为什么我没有收到这个错误,它甚至在 Eclipse 中用 JDT 编译...
无论如何,它仍然无法使用 OpenJDK 7 或 Oracle JDK 7 / 8 为我编译,因此我修改了问题以消除该问题。
编辑2:
快速检查确认这种前向引用现在在 Java 7 中是合法的。应该如此!
编辑3:
我已经在http://bugs.sun.com/上发布了错误报告。如果/当它们被接受时,我会在这里发布链接。