2013-05-27 52 views
10

下面的代码允许`boolean`和`Object`的平等比较?

public class TestComparison { 
    public static void main(String[] args) throws Exception { 
     boolean b = true; 
     Object o = new Boolean(true); 
     System.out.println("comparison result: "+ 
      (o == b)); // Eclipse complains about this expression 
    } 
} 

编译没有错误与javac V1.7.0_15,并打印 “假” 时运行。但是,Eclipse Juno抱怨“不兼容的操作数类型Object和布尔值”。

显然的javac autoboxes原始布尔b,然后比较o和由对象平等autoboxed b,得到false,而Eclipse的拒绝做自动装箱。

根据Java语言规范,哪种行为是正确的?我应该在哪里提交错误?

注:如果我改变的oBoolean类型,事情如预期:月食接受代码和代码打印“真”。

Runnable version on ideone.com

+1

检查您的Eclipse设置,看看是否有什么东西时髦: 项目属性 - > Java编译器 - >错误/警告 - >潜在的规划问题 – blondeamon

+1

要看你“预期”是什么 - 应该把它框'B'和使用引用相等(打印错误)或unbox'o'并使用原始布尔相等(打印真)? –

+0

[Java AutoBoxing规则](http://jcp.org/aboutJava/communityprocess/jsr/tiger/autoboxing.html) –

回答

7

这是你的项目语言级别设置。您可能正在使用具有Java 6语义的Java 7编译器。我在这里没有Eclipse,但是我在IntelliJ中重现了它,即使我使用的编译器是7,在语言级别位于Java 6时出现错误,但我猜Eclipse具有相同的功能。 This link解释它。

+1

这似乎是问题所在。我可以用'javac -source 1.6'重现问题,所以看起来问题是由1.6到1.7的变化引起的。但是,即使对于“编译器符合级别= 1.7”,Eclipse也显示错误。这可能是Eclipse编译器中的一个错误。 – sleske

+0

@sleske我确认所有:/ – A4L

3

关于你的 '笔记' 的代码编译,当o改为Boolean工作:

此代码:

public class Tester{ 
    public static void main(String args[]){ 
    Boolean one = new Boolean(true); 
    Object two = new Boolean(true); 
    boolean three = true; 
    System.out.println("SAME 1:2 " + (one == two) + " 1:3 " + (one == three) + " 2:3 " + (two == three)); 
    System.out.println("EQUAL 1:2 " + (one.equals(two)) + " 1:3 " + (one.equals(three)) + " 2:3 " + (two.equals(three))); 
    } 
} 

会产生这样的结果:

SAME 1:2 false 1:3 true 2:3 false 
EQUAL 1:2 true 1:3 true 2:3 true 

要知道为什么这是,我们需要考虑编译时间各种表达式的类型:

  • one == two一个BooleanObject比较 - 这些都是引用类型,所以测试是引用相等(Java Language Specification, Java SE 7 edition, §15.21.3
  • one == three一个Booleanboolean比较 - 这被视为原始boolean值的比较(§15.21.2); one将被拆箱,并与three进行比较。
  • two == three一个Objectboolean比较 - 在​​这种情况下,boolean通过铸造转换被转换到Object§5.5,在这种情况下,拳击booleanBoolean然后加宽BooleanObject)和两个随后参考平等相比。

EQUAL线要简单得多 - 所有这三种情况都是调用Boolean.equals(Object other),用拳时的说法是three

+0

感谢您的澄清。因此,对于'two == three',投射和装箱/拆箱都是必要的,Java将首先自动装箱,然后投射。 – sleske