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

时间:2012-11-21 20:47:07

标签: java generics openjdk eclipse-jdt compiler-bug

首先,一点背景(如果不感兴趣,可以跳过一点)。我很生气,很困惑!这应该是一个非常简单的用例,事实上我的代码已经使用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 {
}

总结一下,我认为这应该编译得很好,但是Oracle JDK 7&amp; 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

这没有任何意义。返回类型显然是相关的,因为引用的两个方法之一必然frickin'覆盖另一个。我非常有信心这应该有效,事实上,最后1%缺失的唯一原因是,基本上使用仿制药这个基本没有被发现,但我没有发现任何错误报告它。 (不可否认,我没有努力,因为http://bugs.sun.com/只是最糟糕的。你甚至可以根据错误报告是否仍然打开来过滤关键字搜索结果吗?呃。)

对我来说最令人困惑的部分是,当你删除X上Anything的类型边界时,它编译得很好,即使额外的界面与错误无关。

任何人都可以放下心情吗?任何人都知道存在的错误报告,或者以前有过相关经验,可以告诉我问题是什么?如果我没有得到任何确凿的答案,我会提交一些错误报告。

编辑:

有几个人指出我有&lt; S扩展C,C&gt;的前向引用错误。不知道为什么我没有得到这个错误,它甚至在Eclipse中用JDT编译......

无论如何,它仍然无法使用OpenJDK 7或Oracle JDK 7/8编译,所以我修改了问题以解决问题。

编辑2:

快速检查确认这种前向引用现在在Java 7中是合法的。应该是这样!

编辑3:

我在http://bugs.sun.com/上发布了错误报告。如果/当他们被接受,我会在这里发布链接。

3 个答案:

答案 0 :(得分:2)

这显然是你应该报告的javac错误。你可能有更好的运气询问其中一个开放的jdk邮件列表。但这是感恩节所以......

这不是泛型的基本用法,但它非常复杂。

答案 1 :(得分:0)

我已将您的样本输入我的Eclipse Indigo(3.7.1)并立即抱怨Property接口的声明。

  

非法向前引用类型参数C

对于行public S get();

  

返回类型与PropertyConst.get()

不兼容

Property的声明更改为此

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

修复了两个错误,并在JDT和Sun的1.6编译器中编译

答案 2 :(得分:0)

没试过,但在

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

?两个都没有限制。人们需要这样的东西:

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