【问题标题】:Java generics code compiles in eclipse but not in command lineJava泛型代码在eclipse中编译但不在命令行中
【发布时间】:2011-11-10 22:35:46
【问题描述】:

我知道过去有几个关于在 eclipse 中编译但不在命令行中编译的问题,但我还没有找到我的问题的答案。

特别是,我认为我可以设置 eclipse 来使用我的系统编译器,但这仍然没有解决问题。

我目前正在检查:“首选项 -> Java -> 已安装的 JRE”。

这仅包含一个 JRE,它是我的系统之一。

以下是问题的具体情况

我有一个 java 泛型类,它以 Enum 类型作为参数,如下所示:

public class MyClass<T extends Enum<T>>

在类的某个地方,我将一个已知的枚举值与 T 的值进行比较。例如,假设我有这个枚举:

public enum OtherEnum{
 a,
 b
}

然后我测试:

protected void foo(T enumVal){
    if(enumVal == OtherEnum.a){
        // do something
    }
    else if(enumVal == OtherEnum.b){
        // do something else
    }
}

这在 eclipse 中编译没有问题,但在命令行 javac 中我得到这个错误:

无法比较的类型:T 和 OtherEnum

我在两个使用 java 1.6 变体(1.6.0_26 和 1.6.0_16)的系统上进行了尝试。一个是Mac,另一个是linux。他们都给出了同样的错误,而 eclipse 编译没有问题。

所以:

  1. 如何确定 eclipse 使用的是哪个编译器?

  2. 这里有什么问题?

谢谢!

【问题讨论】:

  • 也许这会有所帮助:stackoverflow.com/questions/1173290/…
  • 您是否使用任何外部 .jar 文件?
  • 请张贴SSCEE 说明您遇到的问题。
  • @szielenski 谢谢,这是一个非常有趣的帖子。我确定这些问题是相关的,但我不确定在我的情况下如何处理它。我现在正在研究更多。
  • @Dimme 不,没有外部的,这只是一个小项目。

标签: java eclipse generics javac


【解决方案1】:

这是一个 javac 错误,已在 JDK 7 中修复。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436

【讨论】:

  • 这应该是公认的答案,因为使用 JDK 7+ 编译可以在使用 JDK 6 失败时编译而不会出现任何错误。无需更改源级别合规性。
【解决方案2】:

非常有趣的问题。

以下代码无法编译

    Integer x = null;
    String s = null;
    if(x==s){}   // error: incomparable types

JLS3#15.21.3 [1] 说

如果无法通过强制转换(第 5.5 节)将任一操作数的类型转换为另一操作数的类型,则会发生编译时错误

显然,前面的示例看起来像是一个明显的编程错误,因此规范试图捕捉它并提醒程序员。如果 Java 想要允许它,就不会有任何麻烦。该示例的解决方法是将一侧转换为Object

回到您的问题,我们需要决定是否可以将OtherEnum 转换为T,或者相反。这是一个非常困难的问题;按照 JLS3#5.5 [2] 的程序,答案是否定的。

这取决于OtherEnum是否可以转换为Enum&lt;T&gt;;然后我们可以找到超类型X=Enum&lt;OtherEnum&gt;Y=Enum&lt;T&gt;,它们可以证明是不同的参数化类型。所以强制转换是非法的。

嗯,这样的规范太详细了,有谁会在意呢?

您可以通过将一个转换为Object 来解决它,比如(Object)enumVal == OtherEnum.a

Java 7 的行为有所不同,它会编译您的代码。我不知道原因。 Java7 可能引入了一个新错误。或者它有一个允许代码的新规范(但我们无权访问新规范)。另一种可能性是我误解了“可证明不同的参数化类型”这个术语。但是如果没有正式的定义,很直观Enum&lt;OtherEnum&gt;Enum&lt;T&gt; 是不同的。

参考

[1]http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.21.3

[2]http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#20232

【讨论】:

  • 为什么要解决它。它与实际值的评估无关。
【解决方案3】:

Eclipse 使用它自己的 java 编译器实现(ECJ),与 javac 无关。

Java 的 Eclipse 编译器:

增量 Java 编译器。作为 Eclipse 构建器实现,它是 基于从 VisualAge for Java 编译器演变而来的技术。在 特别是,它允许运行和调试仍然包含的代码 未解决的错误。

【讨论】:

  • 哇,我没有意识到这一点。这很有趣,因为我已经通过 Eclipse 使用了我的代码的这个特定部分,所以肯定有什么东西在那里工作。而且我仍然不确定最初是什么造成了错误。
【解决方案4】:

单独的编译器...使用 == 会强制执行更严格的编译时检查,因此在 CL 中它会强制执行类型比较和错误。在 Eclipse 中,您可以管理编译时间的设置并放宽限制。

您可以尝试 Enum.equals(),它可能不会强制执行如此严格的编译时类型比较。只是一个想法。

【讨论】:

  • 成功了!我还是不明白,为什么原来的版本不能用? == 的两个部分都定义为 Enums 那么为什么类型检查会失败?
  • 因为您比较的是 String "Content" 它的值,而不是 String "Identity" 它在内存中的地址。有意义
  • 在Enums的情况下,身份不应该是一样的吗?
  • 用 == 操作数比较 EnumVal 内容的相等性。 CL 编译器抱怨您的 EnumVal 是无与伦比的类型。我怀疑如果您使用更严格的 EnumVal 类型转换,它可能不会在编译时出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 2012-11-10
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 2015-11-01
  • 2020-08-08
相关资源
最近更新 更多