java實現(xiàn)裝箱和拆箱的方法

本篇文章給大家分享的是有關(guān)java實現(xiàn)裝箱和拆箱的方法,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創(chuàng)新互聯(lián)是一家企業(yè)級云計算解決方案提供商,超15年IDC數(shù)據(jù)中心運營經(jīng)驗。主營GPU顯卡服務器,站群服務器,簡陽服務器托管,海外高防服務器,機柜大帶寬、租用·托管,動態(tài)撥號VPS,海外云手機,海外云服務器,海外服務器租用托管等。

裝箱:
基本類型轉(zhuǎn)變?yōu)榘b器類型的過程,裝箱是通過調(diào)用包裝器類的 valueOf 方法實現(xiàn)的。值類型比引用類型“輕”,原因是他們不作為對象在托管堆中分配,不被垃圾回收,也不通過指針進行引用。但是許多時候都需要獲取值類型的引用,例如,假定要創(chuàng)建ArrayList對象來容納一組point結(jié)構(gòu),代碼如下:
public sealed class Program
{
public static void Main()
{
ArrayList a = new ArrayList();
Point p; //分配一個Point(不在堆中分配)
for (int i = 0; i < 10; i++)
{
p.x = p.y = i; //初始化值類型中的成員
a.Add(p); //對值類型裝箱,將引用添加到ArrayList中
}
}
}
每次循環(huán)迭代都初始化一個ponit的值類型字段,并將該point存儲到ArrayList中。但思考一下ArrayList中究竟存儲了什么?是Point結(jié)構(gòu),Point結(jié)構(gòu)的地址,還是其他完全不同的東西?要知道正確答案,必須研究ArrayList的Add方法,了解他的參數(shù)被定義成什么類型。本例的Add方法原型如下:
public virtual int Add(Object value);
可以看出Add獲取的是一個Object參數(shù),也就是說,Add獲取對托管堆上的一個對象的引用來作為參數(shù)。但之前的代碼傳遞的是p,也就是一個Point,是值類型。為了使代碼正確工作,Point值類型必須轉(zhuǎn)成真正的,在堆中托管的對象,而且必須獲取對該對象的引用。
將值類型轉(zhuǎn)換成引用類型要使用裝箱機制。下面說說對值類型的實例進行裝箱時發(fā)生的事情:
1,在托管堆中分配內(nèi)存。分配的內(nèi)存量是值類型各字段所需的內(nèi)存量,還要加上托管堆所有對象都有的兩個額外成員(類型對象指針和同步塊索引)所需要的內(nèi)存量
2,值類型的字段復制到新分配的堆內(nèi)存
3,返回對象地址?,F(xiàn)在該對象是對象引用;值類型成了引用類型
C#編譯器檢測到上述代碼是向要求引用類型的方法傳遞值類型,所以自動生成代碼對對象進行裝箱。所以在運行時,當前存在于Point值類型實例p中的字段復制到新分配的Point對象中。已裝箱Point對象(現(xiàn)在是引用類型)的地址返回并傳給Add方法。Point對象一直存在于堆中,直至被垃圾回收。Point值類型變量p可被重用,因為ArrayList不知道關(guān)于他的任何事情。在這種情況下,已裝箱類型的生存期超過了為裝箱值類型的生存期。

拆箱:

拆箱就是自動將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型。

拆箱是通過調(diào)用包裝器類的 xxxValue 方法實現(xiàn)的,xxx代表對應的基本數(shù)據(jù)類型。

假定要用一下代碼獲取ArrayList的第一個元素:
Point p=(Point)a[0];
他獲取ArrayList的元素0包含的引用,視圖將其放到Point值類型的實例p中。為此,已裝箱Point對象中的所有字段都必須復制到值類型變量中,后者在線程棧上。CLR分兩步完成復制。第一步獲取已裝箱Point對象中的各個Point字段地址。這個過程稱為拆箱。第二部將字段包含的值從堆復制到基于棧的值類型實例中
拆箱不是直接將裝箱過程倒過來。拆箱的代碼比裝箱低得多。拆箱其實就是獲取指針的過程,該指針指向包含在一個對象中的原始值類型。其實,指針指向的是已裝箱實例中的未裝箱部分。所以和裝箱不同,茶香不要求在內(nèi)存中復制任何字節(jié),知道這個重要區(qū)別后,還應知道的一個重點是,往往緊接著一次字段復制。
已裝箱值類型實例在拆箱是,內(nèi)部發(fā)生下面這些事情:
1,如果包含“對已裝箱值類型的引用”的變量為null,拋出NullReferenceException異常
2,如果引用的對象不是所需值類型的已裝箱實例,拋出InvalidCastException異常
第二條意味著一下代碼的工作方式和你想的可能不一樣:
public static void Main()
{
Int32 x = 5;
Object o = x; //對x裝箱,o引用已裝箱對象
Int16 y = (Int16)o; //拋出InvalidCastException異常
}
從邏輯上說,完全能獲取o引用的已裝箱Int32,將其強制轉(zhuǎn)換為int16.但是對對象進行拆箱時,只能轉(zhuǎn)型為最初未裝箱的值類型--本例Int32,以下是正確寫法:
public static void Main()
{
Int32 x = 5;
Object o = x; //對x裝箱,o引用已裝箱對象
Int16 y = (Int16)(Int32)o; //先拆箱為正確類型,再轉(zhuǎn)型
}
在看以下代碼:
public static void Main()
{
Point p;
p.x = p.y = 1;
Object o = p; //對p裝箱,o引用已裝箱實例
//將Point的x字段變成2
p = (Point)o; //對o拆箱,將字段從已裝箱的實例復制到棧變量中
p.x = 2; //更改棧變量的狀態(tài)
o = p; //將p裝箱,o引用新的已裝箱實例
}
最后三行代碼的唯一目的就是將Point的x字段從1變成2.為此,首先要執(zhí)行一次拆箱,在執(zhí)行一次字段復制,再更改字段(棧上),最后執(zhí)行一次裝箱(在托管堆上創(chuàng)建全新的已裝箱實例)。由此可以看出裝箱拆箱對應用程序性能的影響。
public static void Main()
{
Int32 v = 5;
Object o = v;
v = 123;
Console.WriteLine(v+","+(Int32)o);
}

以上就是java實現(xiàn)裝箱和拆箱的方法,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁標題:java實現(xiàn)裝箱和拆箱的方法
轉(zhuǎn)載來源:http://muchs.cn/article28/ghoicp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣網(wǎng)站導航、網(wǎng)站改版、標簽優(yōu)化、網(wǎng)站制作App開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設網(wǎng)站維護公司