前言
一開始想學學自動拆箱和自動裝箱是被這個名字吸引到,聽上去好像很高階的樣子,其實認真看一下,自動拆箱、自動裝箱就是很簡單的內容。
自動拆箱和自動裝箱
Java為每種基本資料型別都提供了對應的包裝器型別。舉個例子:
public class TestMain { public static void main(String[] args) { Integer i = 10; } }
這個過程中會自動根據數值建立對應的Integer物件,這就是自動裝箱。再看另外一段程式碼:
public class TestMain { public static void main(String[] args) { Integer integer = 10; int i = integer; } }
這個過程中會根據包裝器型別自動將資料轉換為基本型別,這就是自動拆箱。
至於自動裝箱和自動拆箱的原理也很簡單。通過命令列程式,進入CLASSPATH(也就是bin目錄下.class檔案所在的路徑),javap反編譯檢視一下生成的位元組碼:
反編譯出來的內容有很多,我們只關注重點部分:
1 public static void main(java.lang.String[]); 2 flags: ACC_PUBLIC, ACC_STATIC 3 Code: 4 stack=1, locals=3, args_size=1 5 0: iconst_1 6 1: invokestatic #16 // Method java/lang/Integer.valueO 7 f:(I)Ljava/lang/Integer; 8 4: astore_1 9 5: aload_1 10 6: invokevirtual #22 // Method java/lang/Integer.intVal 11 ue:()I 12 9: istore_2 13 10: return
看到在自動裝箱的時候,也就是第6行,Java虛擬機器會自動呼叫Integer的valueOf方法;在自動拆箱的時候,也就是第10行,Java虛擬機器會自動呼叫Integer的intValue方法。這就是自動拆箱和自動裝箱的原理。
小心空指標異常
有這麼一段程式碼:
public static void main(String[] args) throws Exception { Object obj = getObj(null); int i = (Integer)obj; } public static Object getObj(Object obj) { return obj; }
如果執行的話:
Exception in thread "main" java.lang.NullPointerException
at main.Test7.main(Test7.java:8)
這種使用場景很常見,我們把一個int數值放在session或者request中,取出來的時候就是一個類似上面的場景了。所以,小心自動拆箱時候的空指標異常。
小陷阱
看兩段程式碼,第一段程式碼為:
public class TestMain { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1 == i2); System.out.println(i3 == i4); } }
執行結果為:
true false
第二段程式碼為:
public class TestMain { public static void main(String[] args) { Double d1 = 100.0; Double d2 = 100.0; Double d3 = 200.0; Double d4 = 200.0; System.out.println(d1 == d2); System.out.println(d3 == d4); } }
執行結果為:
false false
產生這樣的結果的原因是:Byte、Short、Integer、Long、Char這幾個裝箱類的valueOf()方法是以128位分界線做了快取的,假如是128以下且-128以上的值是會取快取裡面的引用的,以Integer為例,其valueOf(int i)的原始碼為:
public static Integer valueOf(int i) { final int offset = 128; if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); }
而Float、Double則不會,原因也很簡單,因為byte、Short、integer、long、char在某個範圍內的整數個數是有限的,但是float、double這兩個浮點數卻不是。關於這個小知識點,個人提出兩點意見:
1、不重要,除了面試考察求職者對於知識的掌握程度,沒多大用
2、要有快取這個概念,快取對於提高程式執行效率、節省記憶體空間是有很大幫助的