在看深入理解java虛擬機中的自動裝箱的陷阱部分,記錄一下。
public class Test {
public static void main(String[] args) {
try {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
System.out.println(c==d);
System.out.println(e==f);
System.out.println(c==(a+b));
System.out.println(c.equals(a+b));
System.out.println(g==(a+b));
System.out.println(g.equals(a+b));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
運行結果如下:
true
false
true
true
true
false
可能對運行結果比較疑惑,看一下編譯後真正的樣子。
將編譯後的class文件反編譯後得到的內容如下:
public class Test
{
public static void main(String[] args)
{
try
{
Integer a = Integer.valueOf(1);
Integer b = Integer.valueOf(2);
Integer c = Integer.valueOf(3);
Integer d = Integer.valueOf(3);
Integer e = Integer.valueOf(321);
Integer f = Integer.valueOf(321);
Long g = Long.valueOf(3L);
System.out.println(c == d);
System.out.println(e == f);
System.out.println(c.intValue() == a.intValue() + b.intValue());
System.out.println(c.equals(Integer.valueOf(a.intValue() + b.intValue())));
System.out.println(g.longValue() == a.intValue() + b.intValue());
System.out.println(g.equals(Integer.valueOf(a.intValue() + b.intValue())));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
但是還是有疑惑,c==d和e==f的結果爲什麼不同呢?
看一下valueOf的實現:
public static Integer valueOf(int i) {
assert Integer.IntegerCache.high >= 127;
if (i >= Integer.IntegerCache.low && i <= Integer.IntegerCache.high)
return Integer.IntegerCache.cache[i + (-Integer.IntegerCache.low)];
return new Integer(i);
}
原來Integer有個內部類IntegerCache緩存了從-128至127的Integer對象數組,如果在這個範圍內就直接返回數組內的對象,否則就返回新對象。
順便看一下equals(Object obj)方法的實現:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
先判斷是否類型相同,然後在比較基礎類型int值是否相等。
所以,使用對象類型和基礎類型比較的時候需要謹慎一點。