Java實(shí)現(xiàn)拆箱和裝箱的原理解析
什么是拆箱和裝箱?
拆箱和裝箱,其實(shí)是Java 5引入的一個(gè)語法糖,是將 Java的8種基本數(shù)據(jù)類型與其對(duì)應(yīng)的包裝類之間自動(dòng)轉(zhuǎn)換的過程,如下圖:

- 裝箱,將基本數(shù)據(jù)類型轉(zhuǎn)換為對(duì)應(yīng)的包裝類對(duì)象的過程
- 拆箱,將包裝類對(duì)象轉(zhuǎn)換為對(duì)應(yīng)的基本數(shù)據(jù)類型的過程
如下代碼:Integer a 加上 int b 能正確的得出結(jié)果3,其中就包含裝箱和拆箱的過程。
public class UnboxingAndPackingTest {
public static void main(String[] args) {
Integer a = 1;
int b = 2;
int sum = a + b;
System.out.println(sum);// sum=3
}
}
如何實(shí)現(xiàn)拆箱和裝箱?
在上述代碼中,我們并沒有手動(dòng)去執(zhí)行裝箱和拆箱,說明這個(gè)過程是編譯器自動(dòng)完成的,那么,編譯器是如何完成裝箱和拆箱的?為了更好地說明裝箱和拆箱的原理,我們還是延用上面的示例代碼,通過字節(jié)碼層面來進(jìn)行分析。
我們通過 javap -c UnboxingAndPackingTest指令,對(duì)字節(jié)碼進(jìn)行反編譯,如下截圖:

裝箱
將上述裝箱的字節(jié)碼摘出來,如下:
0: iconst_1 1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 4: astore_1
字節(jié)碼的解釋如下:
- iconst_1 將整數(shù)常量1 壓入操作數(shù)棧
- invokestatic #2 調(diào)用
Integer.valueOf(int)方法,將整數(shù)1 裝箱為Integer對(duì)象 - astore_1 將裝箱后的
Integer對(duì)象存儲(chǔ)到局部變量表的索引1 處(即變量 a)
因此,Integer a = 1在字節(jié)碼層面是調(diào)用了Integer.valueOf(int)方法,將整數(shù)1 裝箱為Integer對(duì)象。
拆箱
將上述拆箱的字節(jié)碼摘出來,如下:
7: aload_1 8: invokevirtual #3 // Method java/lang/Integer.intValue:()I 11: iload_2 12: iadd 13: istore_3
字節(jié)碼的解釋如下:
- aload_1 將局部變量表索引1 的
Integer對(duì)象加載到操作數(shù)棧 - invokevirtual #3 調(diào)用了
Integer.intValue()方法,將Integer對(duì)象拆箱為原始類型int - iload_2 將局部變量表索引2 的
int值(即變量 b)加載到操作數(shù)棧 - iadd 將兩個(gè)
int值相加 - istore_3 將相加后的結(jié)果存儲(chǔ)到局部變量表索引3 處(即變量 sum)
通過上述字節(jié)碼的解析,我們可以清楚地看到Java編譯器是如何將裝箱和拆箱操作插入到代碼中的。具體總結(jié)成,裝箱操作通過調(diào)用Integer.valueOf(int)方法實(shí)現(xiàn),而拆箱操作通過調(diào)用Integer.intValue()方法實(shí)現(xiàn)。
Integer.valueof()
上述示例的裝箱操作是通過調(diào)用Integer.valueOf(int)方法實(shí)現(xiàn),因此,我們來看看Integer.valueof()的源碼是如何實(shí)現(xiàn)的,源碼截圖如下:

Integer.valueof()方法,首先會(huì)檢查i是否命中緩存(-128 到 127),如果i在這個(gè)范圍內(nèi),則直接返回緩存中的Integer實(shí)例,如果i不在緩存范圍內(nèi),則創(chuàng)建一個(gè)新的Integer實(shí)例。
這里特別需要注意,Integer的緩存是-128 到 127,如果對(duì)兩個(gè) Integer進(jìn)行比較,一定要特別注意==和equal()的使用。
下面以一個(gè)示例來演示Integer類型的==和equal()使用:

通過Integer的例子,我們可以很輕易的聯(lián)想到Long肯定也存在類似的問題,Long.valueof()源碼如下:

總結(jié)
本文通過具體示例從字節(jié)碼的角度分析了編譯器是如何實(shí)現(xiàn)裝箱和拆箱:
- 裝箱和拆箱是java提供的一個(gè)語法糖,更加簡(jiǎn)化程序員的使用
- 裝箱,將基本數(shù)據(jù)類型轉(zhuǎn)換為對(duì)應(yīng)的包裝類對(duì)象的過程
- 拆箱,將包裝類對(duì)象轉(zhuǎn)換為對(duì)應(yīng)的基本數(shù)據(jù)類型的過程
- 對(duì)于8種基本類型對(duì)應(yīng)的包裝類的比較,推薦使用
equal()而不是==
盡管裝箱和拆箱在 Java中是一個(gè)很簡(jiǎn)單的技術(shù)點(diǎn),但是通過今天的分析,我們不光知道了底層的原理,同時(shí)還分析了Integer.valueof()的源碼,因此,對(duì)于Java 8種基本類型對(duì)應(yīng)的包裝類的比較的原理也有一個(gè)更多的理解,以及在實(shí)際開發(fā)中該如何避坑。
以上就是Java實(shí)現(xiàn)拆箱和裝箱的原理解析的詳細(xì)內(nèi)容,更多關(guān)于Java拆箱和裝箱的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)輕松處理日期和時(shí)間的API小結(jié)
這篇文章主要為大家詳細(xì)介紹了Java中的日期和時(shí)間API,可以輕松處理日期和時(shí)間,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
Spring項(xiàng)目接入DeepSeek的兩種超簡(jiǎn)單的方式分享
DeepSeek?作為一款卓越的國(guó)產(chǎn)?AI?模型,越來越多的公司考慮在自己的應(yīng)用中集成,本文為大家?分享了Spring項(xiàng)目接入DeepSeek的兩種超簡(jiǎn)單的方式,希望對(duì)大家有所幫助2025-02-02
Java根據(jù)表達(dá)式獲取對(duì)象中的值及設(shè)置值的例子
這篇文章主要介紹了Java根據(jù)表達(dá)式獲取對(duì)象中的值及設(shè)置值的例子,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-03-03

