允许“布尔”和“对象”的等式比较?

时间:2013-05-27 09:42:26

标签: java eclipse javac autoboxing

以下代码

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编译时没有错误,并在运行时打印“false”。但是,Eclipse Juno抱怨“不兼容的操作数类型Object和boolean”。

显然,javac自动装箱原始布尔b,然后通过对象相等比较o和自动装箱b,产生false,而Eclipse拒绝进行自动装箱。 / p>

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

注意:如果我将o的类型更改为Boolean,则按预期工作:Eclipse接受代码,代码打印为“true”。

Runnable version on ideone.com

2 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分: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 == twoBooleanObject进行比较 - 这些都是引用类型,因此测试是引用相等(Java Language Specification, Java SE 7 edition, §15.21.3
  • one == threeBooleanboolean进行比较 - 这被视为原始boolean值(§15.21.2)的比较; one已取消装箱,并与three进行比较。
  • two == threeObjectboolean进行比较 - 在​​这种情况下,boolean通过强制转换转换为Object §5.5 ,在这种情况下,将boolean装箱到Boolean,然后将Boolean加宽到Object),然后比较两者的参考相等性。

EQUAL行更简单 - 所有三种情况都是Boolean.equals(Object other)的调用,当参数为three时使用装箱。