最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳細說一說Java自動裝箱與拆箱是什么

 更新時間:2025年10月19日 09:27:31   作者:程序員小假  
自動裝箱與拆箱的機制可以讓我們在Java的變量賦值或者是方法調(diào)用等情況下使用原始類型或者對象類型更加簡單直接,這篇文章主要介紹了Java自動裝箱與拆箱是什么的相關資料,需要的朋友可以參考下

一、核心概念:什么是裝箱與拆箱?

要理解“自動”,首先要理解手動的“裝箱”和“拆箱”。

Java 是一個面向?qū)ο蟮恼Z言,但為了效率,它同時包含了兩種不同的類型系統(tǒng):

  1. 基本數(shù)據(jù)類型byteshortintlongfloatdoublecharboolean。它們直接存儲“值”,存在于棧內(nèi)存中,效率高。

  2. 引用類型:所有 Object 的子類。它們存儲的是對象的“引用”(地址),實際對象存在于堆內(nèi)存中。

在某些場景下(例如使用集合類 ArrayListHashMap),我們必須使用引用類型,因為集合只能存儲對象。這就產(chǎn)生了在基本類型和其對應的包裝類對象之間轉(zhuǎn)換的需求。

包裝類:Java 為每一個基本類型都提供了一個對應的“包裝類”,將這些基本類型“包裝”成對象。

基本數(shù)據(jù)類型包裝類
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

1. 手動裝箱

將一個基本數(shù)據(jù)類型的值,包裝成對應的包裝類對象。

// 手動裝箱
int i = 10;
Integer integerObj = Integer.valueOf(i); // 方式一:推薦,使用了緩存(后面會講)
// 或者
Integer integerObj2 = new Integer(i);    // 方式二:已過時 (Deprecated),不推薦

2. 手動拆箱

從一個包裝類對象中,提取出它所包裹的基本數(shù)據(jù)類型的值。

// 手動拆箱
Integer integerObj = new Integer(10);
int j = integerObj.intValue(); // 從 Integer 對象中取出 int 值

二、什么是自動裝箱與拆箱?

從 Java 5 開始,為了簡化開發(fā),編譯器提供了自動裝箱自動拆箱的功能。它本質(zhì)上是一種“語法糖”,編譯器在背后自動幫我們插入了轉(zhuǎn)換代碼,讓我們可以用更簡潔的方式編寫。

1. 自動裝箱

編譯器自動將基本數(shù)據(jù)類型轉(zhuǎn)換為對應的包裝類對象。

// 自動裝箱
int i = 10;
Integer integerObj = i; // 編譯器背后實際執(zhí)行的是:Integer integerObj = Integer.valueOf(i);

在這行代碼中,一個 int 類型的變量 i 被直接賦給了一個 Integer 類型的引用。編譯器在編譯時,會悄悄地調(diào)用 Integer.valueOf(i) 來完成轉(zhuǎn)換。

2. 自動拆箱

編譯器自動將包裝類對象轉(zhuǎn)換為對應的基本數(shù)據(jù)類型。

// 自動拆箱
Integer integerObj = new Integer(10);
int j = integerObj; // 編譯器背后實際執(zhí)行的是:int j = integerObj.intValue();

在這里,一個 Integer 對象被直接賦給了一個 int 類型的變量。編譯器在編譯時,會悄悄地調(diào)用 integerObj.intValue() 來完成轉(zhuǎn)換。

三、實際應用場景舉例

自動裝箱和拆箱讓我們的代碼變得非常簡潔,尤其是在使用集合類時。

// 在 Java 5 之前,使用 ArrayList 非常麻煩
ArrayList list = new ArrayList();
list.add(Integer.valueOf(1)); // 手動裝箱
int value = (Integer) list.get(0)).intValue(); // 取出來是 Object,要強轉(zhuǎn),再手動拆箱

// 在 Java 5 之后,有了泛型和自動裝箱/拆箱
ArrayList<Integer> list = new ArrayList<>();
list.add(1); // 自動裝箱:int -> Integer
int value = list.get(0); // 自動拆箱:Integer -> int。代碼清晰多了!

其他常見場景:

// 1. 方法調(diào)用時傳遞參數(shù)
public void processInteger(Integer i) { ... }
processInteger(5); // 自動裝箱,將 int 5 轉(zhuǎn)為 Integer

// 2. 運算符運算時
Integer a = 10;
Integer b = 20;
int c = a + b; // a 和 b 先自動拆箱為 int,相加后結果再自動裝箱賦給 Integer(如果接收類型是Integer)
// 等價于:int c = a.intValue() + b.intValue();

// 3. 三目運算符中
boolean flag = true;
Integer i = flag ? 100 : 200; // 100和200都會被自動裝箱為Integer

四、注意事項與陷阱(非常重要!)

自動裝箱雖然方便,但也引入了一些容易忽略的陷阱。

1. 空指針異常

因為自動拆箱實際上是調(diào)用了 xxxValue() 方法,如果包裝類對象是 null,調(diào)用方法就會拋出 NullPointerException。

Integer nullInteger = null;
int i = nullInteger; // 運行時拋出 NullPointerException!
// 背后是:int i = nullInteger.intValue();

2. 性能消耗

雖然單次的裝箱/拆箱開銷很小,但在循環(huán)次數(shù)極多(例如上億次)的場景下,頻繁的創(chuàng)建和銷毀對象會帶來不必要的性能開銷。

long start = System.currentTimeMillis();
Long sum = 0L; // 這里用的是包裝類 Long,會觸發(fā)自動裝箱
for (long i = 0; i < Integer.MAX_VALUE; i++) {
    sum += i; // 每次循環(huán):i自動裝箱為Long,然后sum拆箱為long,相加后再裝箱為Long
}
long end = System.currentTimeMillis();
System.out.println("耗時:" + (end - start));
// 將 Long sum = 0L 改為 long sum = 0L,性能會有巨大提升。

3. 相等比較的陷阱

第一題:以下的代碼會輸出什么?

public class Main{
    public static void main(Sring[] 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

為什么會出現(xiàn)這樣的結果?輸出結果表明 i1 和 i2 指向的是同一個對象,而 i3 和 i4 指向的是不同的對象。此時只需一看源碼便知究竟,下面這段代碼是 Integer 的 valueOf 方法的具體實現(xiàn):

public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }

其中 IntegerCache 類的實現(xiàn)為:

private static class IntegerCache {
        static final int high;
        static final Integer cache[];
 
        static {
            final int low = -128;
 
            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;
 
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }
 
        private IntegerCache() {}
    } 

在通過 valueOf 方法創(chuàng)建 Integer 對象的時候,如果數(shù)值在 [-128,127] 之間,便返回指向 IntegerCache.cache 中已經(jīng)存在的對象的引用;否則創(chuàng)建一個新的 Integer 對象

上面的代碼中 i1 和 i2 的數(shù)值為100,因此會直接從 cache 中取已經(jīng)存在的對象,所以 i1 和 i2 指向的是同一個對象,而 i3 和 i4 則是分別指向不同的對象。

第二題:以下的代碼會輸出什么?

public class Main {
    public static void main(String[] args) {
         
        Double i1 = 100.0;
        Double i2 = 100.0;
        Double i3 = 200.0;
        Double i4 = 200.0;
         
        System.out.println(i1==i2);
        System.out.println(i3==i4);
    }
 }

運行結果:

false
false

原因: 在某個范圍內(nèi)的整型數(shù)值的個數(shù)是有限的,而浮點數(shù)不是。

4. 三目運算符的陷阱

這是一個非常隱蔽的陷阱。

boolean flag = true;
Integer i = flag ? 100 : Integer.valueOf(200);
// 這沒問題,因為 100 和 Integer.valueOf(200) 類型“一致”(都是Integer對象)

Integer i = flag ? 100 : null;
// 當 flag 為 false 時,會發(fā)生什么?
// 編譯器認為 100 是 int,null 是 Integer。為了類型一致,它會將 100 自動裝箱為 Integer,將 null 作為 Integer。
// 所以這里不會報錯,i 會被賦值為 null。

int j = flag ? 100 : Integer.valueOf(200);
// 這也沒問題,因為 Integer.valueOf(200) 會被自動拆箱為 int。

int k = flag ? 100 : null;
// 當 flag 為 false 時,會發(fā)生 NullPointerException!
// 因為編譯器需要得到一個 int 類型的結果,所以它會嘗試對 `null` 進行自動拆箱,調(diào)用 null.intValue()。

總結

  • 自動裝箱基本類型 -> 包裝類,編譯器調(diào)用 valueOf()。

  • 自動拆箱包裝類 -> 基本類型,編譯器調(diào)用 xxxValue()

  • 優(yōu)點:簡化代碼,使基本類型和包裝類之間的轉(zhuǎn)換無縫進行。

  • 陷阱

    1. 空指針:包裝類為 null 時拆箱會拋 NPE。

    2. 性能:在密集循環(huán)中可能帶來開銷。

    3. 比較== 比較包裝類是比較地址,應使用 equals 或先拆箱。

    4. 三目運算符:要注意類型的統(tǒng)一,避免意外的自動拆箱。

到此這篇關于Java自動裝箱與拆箱是什么的文章就介紹到這了,更多相關Java自動裝箱與拆箱內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 關于JWT之token令牌認證登錄

    關于JWT之token令牌認證登錄

    這篇文章主要介紹了關于JWT之token令牌認證登錄,使用JWT能夠保證Token的安全性,且能夠進行Token時效性的檢驗,使用JWT時,登錄成功后將用戶信息生成一串令牌字符串,需要的朋友可以參考下
    2023-05-05
  • ArrayList源碼探秘之Java動態(tài)數(shù)組的實現(xiàn)

    ArrayList源碼探秘之Java動態(tài)數(shù)組的實現(xiàn)

    這篇文章將帶大家從ArrayList源碼來探秘一下Java動態(tài)數(shù)組的實現(xiàn),文中的示例代碼講解詳細,對我們深入了解JavaScript有一定的幫助,需要的可以參考一下
    2023-08-08
  • Java使用新浪微博API通過賬號密碼方式登陸微博的實例

    Java使用新浪微博API通過賬號密碼方式登陸微博的實例

    這篇文章主要介紹了Java使用新浪微博API通過賬號密碼方式登陸微博的實例,一般來說第三方App都是采用OAuth授權認證然后跳轉(zhuǎn)之類的方法,而本文所介紹的賬號方式則更具有自由度,需要的朋友可以參考下
    2016-02-02
  • 一文帶你了解Java中的Object類及類中方法

    一文帶你了解Java中的Object類及類中方法

    Object是Java默認提供的一個類。Java里面除了Object類,所有的類都是存在繼承關系的。默認會繼承Object父?類。即所有類的對象都可以使用Object的引用進行接收。本文就來為大家詳細講講Object類及類中方法,感興趣的可以了解一下
    2022-08-08
  • Java中的static的使用指南

    Java中的static的使用指南

    本文給大家簡單總結了下java中的static的使用注意事項及方法,非常的實用,有需要的小伙伴可以參考下
    2016-04-04
  • 關于Maven的使用,這些你都真的了解么

    關于Maven的使用,這些你都真的了解么

    這篇文章主要介紹了關于Maven的使用,這些你都真的了解么?具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 解析java創(chuàng)建對象的全過程

    解析java創(chuàng)建對象的全過程

    文章總結了Java創(chuàng)建對象的幾種方式,包括使用new關鍵字、反射、clone和反序列化,此外,還詳細描述了創(chuàng)建對象的過程,包括類加載、內(nèi)存分配和對象初始化,最后,強調(diào)了并發(fā)情況下的操作原子性問題
    2025-12-12
  • 使用SpringBoot進行身份驗證和授權的示例詳解

    使用SpringBoot進行身份驗證和授權的示例詳解

    在廣闊的 Web 開發(fā)世界中,身份驗證是每個數(shù)字領域的守護者,在本教程中,我們將了解如何以本機方式保護、驗證和授權 Spring-Boot 應用程序的用戶,并遵循框架的良好實踐,希望對大家有所幫助
    2023-11-11
  • springboot集成nacos讀取nacos配置數(shù)據(jù)的原理

    springboot集成nacos讀取nacos配置數(shù)據(jù)的原理

    這篇文章主要介紹了springboot集成nacos讀取nacos配置數(shù)據(jù)的原理,文中有詳細的代碼流程,對大家學習springboot集成nacos有一定的幫助,需要的朋友可以參考下
    2023-05-05
  • SpringBoot中的@RestControllerAdvice注解詳解

    SpringBoot中的@RestControllerAdvice注解詳解

    這篇文章主要介紹了SpringBoot中的@RestControllerAdvice注解詳解,RestControllerAdvice注解用于創(chuàng)建全局異常處理類,用于捕獲和處理整個應用程序中的異常,需要的朋友可以參考下
    2024-01-01

最新評論

荆州市| 广昌县| 三穗县| 凤翔县| 布拖县| 都安| 石城县| 南丹县| 自治县| 曲松县| 金华市| 奉贤区| 凌海市| 临湘市| 临猗县| 张北县| 洪江市| 改则县| 科尔| 隆德县| 刚察县| 留坝县| 苍梧县| 新昌县| 大冶市| 揭阳市| 乃东县| 连南| 青川县| 尚义县| 花莲市| 龙里县| 松潘县| 普安县| 奈曼旗| 安图县| 来宾市| 保亭| 台安县| 安义县| 阿勒泰市|