這是jdk1.5以後才引入的新的內容,作為秉承發表是最好的記憶,毅然決定還是用一篇博客來代替我的記憶:
java語言規範中說:在許多情況下包裝與解包裝是由編譯器自行完成的(在這種情況下包裝成為裝箱,解包裝稱為拆箱);
其實按照我自己的理解自動裝箱就可以簡單的理解為將基本資料型別封裝為物件類型,來符合java的物件導向;例如用int來舉例:
複製代碼代碼如下:
//聲明一個Integer對象
Integer num = 10;
//以上的宣告就是用到了自動的裝箱:解析為
Integer num = new Integer(10);以上就是一個很好的體現,因為10是屬於基本資料類型的,原則上它是不能直接賦值給一個物件Integer的,但jdk1.5後你就可以進行這樣的聲明,這就是自動裝箱的魅力自動將基本資料類型轉換為對應的封裝類型。成為一個物件以後就可以呼叫物件所聲明的所有的方法自動拆箱:故名思議就是將物件重新轉換為基本資料類型:
//裝箱
Integer num = 10;
//拆箱
int num1 = num;自動拆箱有個很典型的用法就是在進行運算的時候:因為物件時不恩直接進行運算的,而是要轉化為基本資料型別後才能進行加減乘除
Integer num = 10;
//進行計算時隱含的有自動拆箱
System.out.print(num--);哈哈應該覺得很簡單吧,下面我再來講點稍微難點的,
//在-128~127 之外的數
Integer num1 = 297; Integer num2 = 297;
System.out.println("num1==num2: "+(num1==num2));
// 在-128~127 之內的數
Integer num3 = 97; Integer num4 = 97;
System.out.println("num3==num4: "+(num3==num4)); 印出來的結果是:num1==num2: false num3==num4: true
很奇怪吧:這就歸結於java對於Integer與int的自動裝箱與拆箱的設計,是一種模式:叫做享元模式(flyweight)
為了增加對簡單數字的重利用,java定義:在自動裝箱時對於值從128到127之間的值,它們被裝箱為Integer對象後,會存在內存中被重用,始終只存在一個對象而如果超過了從128到127之間的值,被裝箱後的Integer物件並不會被重用,即相當於每次裝箱時都新建一個Integer物件;明白了吧以上的現像是由於使用了自動裝箱所引起的,如果你沒有使用自動裝箱,而是跟一般類別一樣,用new來進行實例化,就會每次new就都一個新的物件;
這個的自動裝箱拆箱不僅在基本資料型別中有應用,在String類別中也有應用,例如我們常聲明一個String物件時:
複製代碼代碼如下:
String str = "sl";
//代替下面的聲明方式
String str = new String("sl");
基本資料(Primitive)類型的自動裝箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0開始提供的功能。雖然為您打包基本資料類型提供了方便,但提供方便的同時表示隱藏了細節,建議在能夠區分基本資料類型與物件的差異時再使用。
autoboxing和unboxing
在Java中,所有要處理的東西幾乎都是對象(Object),例如之前所使用的Scanner是對象,字串(String)也是對象,之後還會看到更多的對象。然而基本(Primitive)資料型態不是對象,也就是您使用int、double、boolean等定義的變量,以及您在中直接寫下的字面常數。
在前一個小節已經大致看到了操作物件的方便性,而使用Java有一段時間的人都知道,有時需要將基本資料型別轉換為物件。例如使用Map物件要put()方法時,需要傳入的參數是物件而不是基本資料類型。
要使用打包類型(Wrapper Types)才能將基本資料類型包裝為對象,前一個小節您已經知道在J2SE 5.0之前,要使用以下語句才能將int包裝為一個Integer對象:Integer integer = new Integer(10) ;
在J2SE 5.0之後提供了自動裝箱的功能,您可以直接使用以下語句來打包基本資料類型:Integer integer = 10;
在進行編譯時,編譯器會自動根據您寫下的語句,判斷是否要進行自動裝箱動作。在上例中integer參考的會是Integer類別的實例。同樣的動作可以適用於boolean、byte、short、char、long、float、double等基本資料類型,分別會使用對應的打包類型(Wrapper Types)Boolean、Byte、Short、Character、Long、Float或Double。以下直接使用自動裝箱功能來改寫範例4.4。
範例4.5 AutoBoxDemo.java
複製代碼代碼如下:
public class AutoBoxDemo {
public static void main(String[] args) {
Integer data1 = 10;
Integer data2 = 20;
// 轉為double值再除以3
System.out.println(data1.doubleValue() / 3);
// 進行兩個值的比較
System.out.println(data1.compareTo(data2));
}
}
程式看來簡潔了許多,data1與data2運行時就是Integer的實例,可以直接進行物件操作。的結果如下:
3.3333333333333335
1
自動裝箱運用的方法還可以如下:
複製代碼代碼如下:
int i = 10;
Integer integer = i;
也可以使用更一般化的java.lang.Number類別來自動裝箱。例如:
Number number = 3.14f;
3.14f會先被自動裝箱為Float,然後指定給number。
從J2SE 5.0開始可以自動裝箱,也可以自動拆箱(unboxing),也就是將物件中的基本資料形態資訊從物件中自動取出。例如下面這樣寫是可以的:
複製代碼代碼如下:
Integer fooInteger = 10;
int fooPrimitive = fooInteger;
fooInteger引用至自動裝箱為Integer的實例後,如果被指定給一個int類型的變數fooPrimitive,則會自動變成int型別再指定給fooPrimitive。在運算時,也可以進行自動裝箱與拆箱。例如:
複製代碼代碼如下:
Integer i = 10;
System.out.println(i + 10);
System.out.println(i++);
上例會顯示20與10,編譯器會自動進行自動裝箱與拆箱,也就是10會先被裝箱,然後在i + 10時會先拆箱,進行加法運算;i++該行也是先拆箱再進行遞增運算。再來看一個例子:
複製代碼代碼如下:
Boolean boo = true;
System.out.println(boo && false);
同樣的boo原來是Boolean的實例,在進行AND運算時,會先將boo拆箱,再與false進行AND運算,結果會顯示false。
////////////////////////////////////////////////// /////////////////
裝箱:從基本型別轉換成Object型,稱為裝箱;***拆箱:從Object轉換乘基本型別的操作,稱為拆箱。 這個操作在反射過程中用的比較的多。
裝箱:在堆中建立一個Object實例,把你指定的值複製成去;***拆箱:判別引用指向的堆中資訊是否是要拆成的類型,是取出堆中值送給棧中變數,否則報異常
////////////////////////////////////////////////// /////////////////
裝箱是值類型到object類型或到該值類型所實現的任何介面類型的隱士轉換。
將一個值類型裝箱會指派一個物件實例並將該值複製到新的物件中。
複製代碼代碼如下:
int i=123;
object o=i;
這句話的結果是在堆疊上創建一個物件o,而該物件在堆上引用int類型的值。該值是賦值給變數i
的值類型值的一個副本。
下面是顯示執行裝箱轉換
複製代碼代碼如下:
int i=123;
ojbect o=(object)i;
此例將整數變數i透過裝箱轉換為物件o。這樣,儲存在變數i中的值就從123改為456。此例顯示物件保留了內容的原始副本。即123。
取消裝箱是從object類型到值類型或從介面類型到實現該介面的值類型的顯示轉換。取消裝箱操作包括:
檢查物件實例,確保它是給定值類型的一個裝箱值。
將該值從實例複製到值類型變數中。
例子:
複製代碼代碼如下:
int i=123;
object box=i;
int j=(int)box;