2012-09-01 234 views
11

我知道Double是一個包裝類,它包裝了double數字。今天,我看到了另一個主要區別:Java:不同的double和double比較

double a = 1.0; 
double b = 1.0; 
Double c = 1.0; 
Double d = 1.0; 
System.out.println(a == b); // true 
System.out.println(c == d); // false 

對我來說很奇怪!

所以,如果我們使用Double,每一次,我們必須做這樣的事情:

private static final double delta = 0.0001; 
System.out.println(Math.abs(c-d) < delta); 

我無法解釋爲什麼雙化妝直接比較是錯誤的。請爲我解釋。

謝謝:)

+8

使用'c.equals(d)'而不是'=='。 '=='只檢查引用。 – Baz

+2

@巴茲啊,我明白了。雙是一個類。它會比較對象而不是比較值。這個問題喜歡我們用'String'做的事情。應該使用'equals'而不是== == :) – hqt

+0

是的,正好... – Baz

回答

21

cd在技術上是兩個不同的對象和==運營商只比較引用。

c.equals(d) 

更好,因爲它比較值而不是參考。但仍然不理想。直接比較浮點值應始終考慮一些錯誤(epsilon)(Math.abs(c - d) < epsilon)。

需要注意的是:

Integer c = 1; 
Integer d = 1; 

這裏比較會產生true,但是這更復雜(Integer內部緩存,在JavaDoc of Integer.valueOf()描述):

這種方法將範圍始終緩存值 - 128到127(含),並且可以緩存該範圍之外的其他值。

爲什麼valueOf()?因爲這個方法隱含用於實現自動裝箱:

Integer c = Integer.valueOf(1); 
Integer d = Integer.valueOf(1); 

+0

哦。我明白了。這個問題喜歡當我們使用字符串類。但你的第二個例子很有趣。你能告訴我爲什麼這是真的,當整數:) – hqt

+0

@hqt:檢查鏈接*另請參閱*我的答案部分。 –

+1

@hqt你可以稱它爲整數池。大小<-128,127> - 使用equals()和== == – dantuch

3

請參閱使用equals()支票2個對象的相等。 ==檢查2個引用是否引用了內存中的同一個對象。

4

當應用於類別表達式時,==始終執行參考比較(JLS section 15.21.3)。所以這條線:

System.out.println(c == d); 

是檢查是否cd指向同一個對象。 Java中的自動裝箱總是(我相信)爲floatdouble創建一個新對象(對於整型,情況更爲複雜)。因此cd指的是不同的對象,所以它打印false

如果你想比較平等對象,你需要調用equals明確:

System.out.println(c.equals(d)); 

隨着double,它使用數字,而不是平等 - 在section 15.21.1規定。因此行爲上的差異。


對於積分自動裝箱,「小」值緩存 - 所以自動裝箱5(說)會每次都返回相同的參考。 「小」的定義是特定於實現的,但保證在-128至127的範圍內。有關詳細信息,請參閱section 5.1.7的底部。

+0

+1很棒的細節! –

+1

關於整數緩存,你能告訴我爲什麼你可以知道這個嗎?我在任何我讀過的java書中都沒有看到這些東西。 (並且我不認爲你學習了所有的Java規範:D) – hqt

+0

@hqt即使你不太瞭解所有的規範,過了一段時間你就會知道它的大部分。這是一個很好的習慣,只要你看到一些你不知道如何工作的東西,就去檢查規格和/或來源。新知識使您成爲更好的開發人員,並降低錯誤風險。 –

2

檢查原語類型時,對於==,內容檢查僅可靠。對於物體類型,最好使用equals方法:

c.equals(d)