自動裝箱:小心使用 boxing

    自動裝箱與拆箱的功能事實上是編譯器來幫你的忙,編譯器在編譯時期依你所編寫的語法,決定是否進行裝箱或拆箱動作。例如:  
    Integer i = 100;
    相當於編譯器自動爲你作以下的語法編譯:  
    Integer i = new Integer(100);
    所以自動裝箱與拆箱的功能是所謂的“編譯器蜜糖”(Compiler Sugar),雖然使用這個功能很方便,但在程序運行階段你得了解Java的語義。                例如下面的程序是可以通過編譯的:  
    Integer i = null;int j = i;
    這樣的語法在編譯時期是合法的,但是在運行時期會有錯誤,因爲這種寫法相當於:  
    Integer i = null;int j = i.intValue();
    null表示i沒有參考至任何的對象實體,它可以合法地指定給對象參考名稱。由於實際上i並沒有參考至任何的對象,所以也就不可能操作intValue()方法,這樣上面的寫法在運行時會出現NullPointerException錯誤。  
    自動裝箱、拆箱的功能提供了方便性,但隱藏了一些細節,所以必須小心。再來看“AutoBoxDemo1.java ”,你認爲結果是什麼呢?  

AutoBoxDemo1.java: 
1. public class AutoBoxDemo1 {   
2.     public static void main(String[] args) {   
3.         Integer i1 = 127;  
4.         Integer i2 = 127;   
5.         if (i1 == i2)    
6.             System.out.println("i1 == i2");   
7.         else    
8.             System.out.println("i1 != i2");   
9.     }   
10.} 

  
    從自動裝箱與拆箱的機制來看,可能會覺得結果是顯示i1 == i2,你是對的。 
    那麼“AutoBoxDemo2.java ”的這個程序,你覺得結果是什麼?  
AutoBoxDemo2.java: 
1. public class AutoBoxDemo2{   
2.     public static void main(String[] args) {   
3.         Integer i1 = 128;   
4.         Integer i2 = 128;   
5.         if (i1 == i2)    
6.             System.out.println("i1 == i2");   
7.         else    
8.             System.out.println("i1 != i2");   
9.     }   
10.}   
    結果是顯示i1 != i2,這有些令人驚訝,兩個範例語法完全一樣,只不過改個數值而已,結果卻相反。  
    其實這與==運算符的比較有關,==是用來比較兩個基本數據類型的變量值是否相等,事實上==也用於判斷兩個對象變量名稱是否參考至同一個對象。  在自動裝箱時對於值從–128到127之間的值,它們被裝箱爲Integer對象後,會存在內存中被重用,所以範例4.6中使用==進行比較 時,i1 與 i2實際上參考至同一個對象。如果超過了從–128到127之間的值,被裝箱後的Integer對象並不會被重用,即相當於每次裝箱時都新建一個 Integer對象,所以
    “AutoBoxDemo2.java”使用==進行比較時,i1與i2參考的是不同的對象。  所以不要過分依賴自動裝箱與拆箱,你還是必須知道基本數據類型與對象的差異。最好還是依正規的方式來寫,而不是依賴編譯器蜜糖(Compiler Sugar)。例如“AutoBoxDemo2.java”必須改寫爲“AutoBoxDemo3.java ”纔是正確的。  
AutoBoxDemo3.java: 
1. public class AutoBoxDemo3 {   
2.     public static void main(String[] args) {   
3.         Integer i1 = 128;   
4.         Integer i2 = 128;   
5.         if (i1.equals(i2))    
6.             System.out.println("i1 == i2");   
7.         else    
8.             System.out.println("i1 != i2");   
9.     }   
10.}  
 
    結果這次是顯示i1 == i2。使用這樣的寫法,相信也會比較放心一些,對於這些方便但隱藏細節的功能到底要不要用呢?基本上只有一個原則:如果你不確定就不要用。
發佈了15 篇原創文章 · 獲贊 9 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章