我知道过去有几个问题是关于在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正在编译而没有任何问题。
所以:
如何确定使用哪个编译器eclipse?
这里有什么问题?
谢谢!
答案 0 :(得分:5)
这是一个已在JDK 7中修复的javac错误。
请参阅http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436
答案 1 :(得分: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<T>
;然后我们可以找到超级类型X=Enum<OtherEnum>
和Y=Enum<T>
,它们是可证明不同的参数化类型。所以演员是非法的。
那么,这样的规范太复杂了,谁在正确的思想中会关心呢?
您可以通过将其转换为Object
来解决此问题,例如(Object)enumVal == OtherEnum.a
Java 7的行为不同,它确实编译了你的代码。我不知道原因。 Java7可能引入了一个新bug。或者它有一个允许代码的新规范(但我们无法访问新规范)。另一种可能性是我误解了“可证明不同的参数化类型”这个术语;但是,如果没有正式的定义,Enum<OtherEnum>
和Enum<T>
是截然不同的直观。
REF
[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
答案 2 :(得分:1)
Eclipse使用它自己的java编译器实现(ECJ),它与javac无关。
Eclipse Compiler for Java:
增量Java编译器。实现为Eclipse构建器,它是 基于从VisualAge for Java编译器演化而来的技术。在 特别是,它允许运行和调试仍然包含的代码 未解决的错误。
答案 3 :(得分:0)
单独的编译器...使用==强制进行更严格的编译时间检查,因此在CL中强制执行类型比较和错误。在Eclipse中,您可以管理编译时的设置,并放松限制。
您可以尝试Enum.equals(),它可能不会强制执行此类严格的编译时类型比较。只是一个想法。