【问题标题】:Possible Java compiler bug! Program does not compile with some compilers可能的 Java 编译器错误!某些编译器无法编译程序
【发布时间】:2012-11-10 05:02:51
【问题描述】:

首先,介绍一些背景知识(如果不感兴趣,请略略略过)。我很生气和困惑!这应该是一个非常简单的用例,实际上我的代码已经用 Eclipse JDT 编译器编译得很好,所以直到现在我一直在配置 Maven 以确保这样做。 虽然它不能与 Oracle JDK 和 OpenJDK 一起编译,但它一直困扰着我,因为我认为这实际上可能是我的代码有问题,所以我再次调查了它。

我认为错误可能在于 JDT 编译器允许它编译,而不是 Oracle JDK 和 OpenJDK 不允许它,我也测试过这两者。有问题的原始代码要复杂得多,因此我更难看出问题出在哪里,事实上,我很惊讶地看到在仍未编译的情况下可以将问题减少到何种程度。

无论是 Eclipse JDT 编译器还是 Oracle JDK 和 OpenJDK 都有一个相当大的(恕我直言)错误。

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 & 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 上任何东西的类型边界时,它编译得很好,即使额外的接口与错误无关。

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

编辑:

有几个人指出我在使用 时遇到了前向引用错误。不知道为什么我没有收到这个错误,它甚至在 Eclipse 中用 JDT 编译...

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

编辑 2:

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

编辑 3:

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

【问题讨论】:

  • 问题是?不等于?
  • 您是在 java 6 还是 7 上运行测试的?
  • 如果你删除Anything接口你还有错误吗?
  • 您是否还注意到 eclipse 中的“非法前向引用”错误? (另见this question)反转属性的泛型声明的参数
  • 好的,再次阅读问题。适用于 JDK 1.5.0_10(需要删除接口 @Override)、1.6.0_27。 1.7.0_07 和 1.7.0_09 失败。

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


【解决方案1】:

没试过,但在

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

? 都没有限制。需要类似的东西:

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

【讨论】:

  • 您不应该需要那个 afaiu,在这种情况下,属性接口定义中指定的现有边界应该隐式结转。 Property, ?> 并不意味着 Property 可以用字面上的任何东西进行参数化,只是我们不关心它在这里是如何参数化的。这里的Property的实际参数化将针对Bug参数化时提供给X的类型进行验证......抱歉解释的尴尬,这不容易说清楚......
【解决方案2】:

这显然是一个您应该报告的 javac 错误。在开放的 jdk 邮件列表之一上提问可能会更好。但现在是感恩节,所以......

虽然这不是泛型的基本用法,但它相当复杂。

【讨论】:

  • 感谢信任投票!我只是想先在这里问一下,通过提交一份愚蠢的错误报告来避免尴尬……不过,我会确保在某个时候提交一份。你应该看看我对仿制药的其他一些滥用,哈哈……有时这是犯罪行为。我知道这可能不是一件好事,但这是一个个人项目,我很享受;)。如果确认此错误,我实际上可能还有其他一些错误要报告,这远不是 JDT 不同意 Oracle/OpenJDK 的唯一地方。是的,我忘了 TG,我住在英国。
  • P.S.如果我在接下来的一天左右没有发现任何分歧,我会将这个答案标记为正确。
  • 嗯,此时看起来已经很清晰了,所以标记为已回答。感谢您的帮助,也感谢其他所有测试过的人 :)
【解决方案3】:

我已将您的示例输入到我的 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 编译器中编译

【讨论】:

  • 干杯,虽然在 Eclipse Juno、Sun 1.7 或 1.8 或 OpenJDK 中并没有为我修复错误。
  • 抱歉,该评论具有误导性 - 即使使用 Eclipse Juno 中的前向引用,它也能正常编译...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 2021-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多