測試代碼:
System.out.println(0L == 0);//true
System.out.println(((Long)0L).equals(0));//false
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 1000;//如果int values between -128 and 127,VM使用相同的對象,否則創建新的對象。
Integer i4 = 1000;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//false
Autoboxing和unboxing又名拆箱和裝箱,簡單一點講,就是從primitive轉換到wrapper class,例如int類型到Integer類型就是裝箱,而Integer類型到int類型則是拆箱。當然,這里的裝箱和拆箱都是auto的,是JVM在工作的內容,事實上不用我們手寫,然而也有手寫的對應方式,如下所示:
1 int i=10;
2 Integer a=new Integer(i);//裝箱的操作
3 int j=a.intValue();//拆箱的操作
上面是手動的,在Java5.0之后已經在JVM中有了自動的裝箱和拆箱的轉換,如下所示:
1 int i=10;
2 Integer b=i;//自動的裝箱
3 int k=b;//自動的拆箱
裝箱和拆箱就是這么簡單,下面可以看一下自增是怎么一個過程,這是一個很有意思的事情,遞減也是一樣。
1 Integer d=new Integer(10);
2 d++;//這條語句使得d先拆箱,然后進行++操作,而后對結果再裝箱
上面的這條語句,使得Java保證了wrapper class也可以是正常使用通用的操作符,但這絕對不是C++中的運算符重載。你還可以試着分析三元表達式和條件表達式中的裝箱拆箱過程。
這里需要注意的一點就是裝箱和拆箱在Method Overload時候的問題,例如下面:
1 public void doSomething(double num);
2 public void doSomething(Integer num);
在一個類中有這么兩個函數,那么對於整數int k,如果進行doSomething(k)的調用,會調用哪個呢?
在Java1.4中,顯然是調用double類型的函數,然而,現在有了自動的拆箱和裝箱之后會調用哪個呢?還double類型的函數。這樣可以保證以前的代碼在現在新的版本中也可以正確的運行。(向下兼容,Backwards compatibility,在計算機中指在一個程序或者類庫更新到較新的版本后,用舊的版本程序創建的文檔或系統仍能被正常操作或使用,或在舊版本的類庫的基礎上開發的程序仍能正常編譯運行的情況。)
注意,Java5中,Method的解析是三個pass的過程:
A.編譯器會試着不用任何的boxing和unboxing,或者啟用vararg(可變參數)來定位正確的method。這會找到根據Java1.4的規則而會調用的任何method。
B.如果第一個pass失敗了,編譯器會再度嘗試解析method,但這次會允許boxing和unboxing轉換。具有vararg的method不在這次pass的考慮中。
C.如果第二個pass也失敗了,編譯器會做最后一次的嘗試,允許boxing和unboxing,且同時也考慮到vararg method。