2013-05-27 53 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