用於比較原始包裝物件(如 Integer)的陷阱
(這個陷阱同樣適用於所有原始包裝型別,但我們將為 Integer
和 int
進行說明。)
使用 Integer
物件時,很有可能使用 ==
來比較值,因為這是你對 int
值所做的。在某些情況下,這似乎有效:
Integer int1_1 = Integer.valueOf("1");
Integer int1_2 = Integer.valueOf(1);
System.out.println("int1_1 == int1_2: " + (int1_1 == int1_2)); // true
System.out.println("int1_1 equals int1_2: " + int1_1.equals(int1_2)); // true
在這裡,我們建立了兩個 Integer
物件,其值為 1
並進行比較(在本例中,我們建立了一個來自 String
,另一個來自 int
文字。還有其他選擇)。此外,我們觀察到兩種比較方法(==
和 equals
)都產生了 true
。
當我們選擇不同的值時,此行為會更改:
Integer int2_1 = Integer.valueOf("1000");
Integer int2_2 = Integer.valueOf(1000);
System.out.println("int2_1 == int2_2: " + (int2_1 == int2_2)); // false
System.out.println("int2_1 equals int2_2: " + int2_1.equals(int2_2)); // true
在這種情況下,只有 equals
比較產生正確的結果。
這種行為差異的原因是,JVM 維護了 -128 到 127 範圍內的 Integer
物件的快取。(可以使用系統屬性“java.lang.Integer.IntegerCache.high”覆蓋上限值或者 JVM 引數“-XX:AutoBoxCacheMax = size”)。對於此範圍內的值,Integer.valueOf()
將返回快取值,而不是建立新值。
因此,在第一個示例中,Integer.valueOf(1)
和 Integer.valueOf("1")
呼叫返回了相同的快取 Integer
例項。相比之下,在第二個例子中,Integer.valueOf(1000)
和 Integer.valueOf("1000")
都建立並返回了新的 Integer
物件。
參考型別的 ==
運算子測試引用相等性(即同一物件)。因此,在第一個例子中,int1_1 == int1_2
是 true
,因為引用是相同的。在第二個例子中,int2_1 == int2_2
是假的,因為引用是不同的。