這個是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;