JAVA自動裝箱拆箱


引言

Java 中的**裝箱(Boxing)拆箱(Unboxing)**是自動類型轉換的機制,用于在基本數據類型(如 intlong 等)和其對應的包裝類(如 IntegerLong 等)之間進行轉換。這種機制簡化了代碼的編寫,但也可能引發一些性能問題或意外行為。

通過以下案例和字節碼分析,我們將深入探討裝箱和拆箱的原理及其在實際開發中的應用。


案例代碼與輸出

public class Test {public static void main(String[] args) {Integer a = 1;          // 自動裝箱Integer b = 2;          // 自動裝箱Integer c = 3;          // 自動裝箱Integer d = 3;          // 自動裝箱Integer e = 321;        // 自動裝箱Integer f = 321;        // 自動裝箱Long g = 3L;            // 自動裝箱System.out.println(c == d);           // trueSystem.out.println(e == f);           // falseSystem.out.println(c == (a + b));     // trueSystem.out.println(c.equals(a + b));  // trueSystem.out.println(g == (a + b));     // trueSystem.out.println(g.equals(a + b));  // false}
}
輸出結果:
true
false
true
true
true
false

逐行解析與字節碼分析

1. c == d 輸出 true
  • 原因cd 都是 Integer 類型,值為 3
  • 裝箱過程Integer c = 3 實際上被編譯器翻譯為 Integer c = Integer.valueOf(3)
  • 緩存機制Integer.valueOf 方法會對 -128 ~ 127 范圍內的整數使用緩存池。因此,cd 指向同一個緩存對象。
  • 字節碼分析
     ICONST_3INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;ASTORE 3ICONST_3INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;ASTORE 4
    
    • ASTORE 3ASTORE 4 分別存儲 cd
    • 因為 3 在緩存范圍內,cd 引用的是同一個對象,因此 c == d 返回 true

2. e == f 輸出 false
  • 原因ef 的值為 321,超出了 Integer 緩存范圍(默認 -128 ~ 127),因此每次調用 Integer.valueOf(321) 都會創建新的對象。
  • 字節碼分析
     SIPUSH 321INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;ASTORE 5SIPUSH 321INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;ASTORE 6
    
    • SIPUSH 將常量 321 壓入棧頂。
    • INVOKESTATIC 調用 Integer.valueOf 方法。
    • 因為 321 不在緩存范圍內,ef 是不同的對象,因此 e == f 返回 false

3. c == (a + b) 輸出 true
  • 原因a + b 的計算涉及拆箱操作,a.intValue()b.intValue() 相加得到一個 int 值,然后與 c 進行比較時,c 也會被拆箱為 int
  • 拆箱過程
    • a + b 被翻譯為 a.intValue() + b.intValue()
    • c == (a + b) 被翻譯為 c.intValue() == (a.intValue() + b.intValue())
  • 字節碼分析
     ALOAD 3INVOKEVIRTUAL java/lang/Integer.intValue ()IALOAD 1INVOKEVIRTUAL java/lang/Integer.intValue ()IALOAD 2INVOKEVIRTUAL java/lang/Integer.intValue ()IIADDIF_ICMPNE L14
    
    • INVOKEVIRTUAL 調用 intValue 方法完成拆箱。
    • 最終比較的是兩個 int 值,因此 c == (a + b) 返回 true

4. c.equals(a + b) 輸出 true
  • 原因equals 方法比較的是值,而不是引用。a + b 的結果是一個 int,會被自動裝箱為 Integer,然后調用 equals 方法進行比較。
  • 字節碼分析
     ALOAD 3ALOAD 1INVOKEVIRTUAL java/lang/Integer.intValue ()IALOAD 2INVOKEVIRTUAL java/lang/Integer.intValue ()IIADDINVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;INVOKEVIRTUAL java/lang/Integer.equals (Ljava/lang/Object;)Z
    
    • a + b 的結果被裝箱為 Integer
    • equals 方法比較的是兩個 Integer 的值,因此返回 true

5. g == (a + b) 輸出 true
  • 原因gLong 類型,a + b 的結果是 int 類型。在比較時,a + b 被提升為 long 類型(I2L 指令),然后與 g 的值進行比較。
  • 字節碼分析
     ALOAD 7INVOKEVIRTUAL java/lang/Long.longValue ()JALOAD 1INVOKEVIRTUAL java/lang/Integer.intValue ()IALOAD 2INVOKEVIRTUAL java/lang/Integer.intValue ()IIADDI2LLCMPIFNE L18
    
    • I2Lint 提升為 long
    • LCMP 比較兩個 long 值,因此 g == (a + b) 返回 true

6. g.equals(a + b) 輸出 false
  • 原因equals 方法比較的是對象類型和值。a + b 的結果是 int 類型,會被裝箱為 Integer,而 gLong 類型,因此 equals 返回 false
  • 字節碼分析
     ALOAD 7ALOAD 1INVOKEVIRTUAL java/lang/Integer.intValue ()IALOAD 2INVOKEVIRTUAL java/lang/Integer.intValue ()IIADDINVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;INVOKEVIRTUAL java/lang/Long.equals (Ljava/lang/Object;)Z
    
    • a + b 的結果被裝箱為 Integer
    • equals 方法檢查類型不匹配(Long vs Integer),因此返回 false

總結與注意事項

  1. 裝箱與拆箱的本質

    • 裝箱:將基本類型(如 int)轉換為包裝類(如 Integer)。底層調用 valueOf 方法。
    • 拆箱:將包裝類(如 Integer)轉換為基本類型(如 int)。底層調用 intValue 方法。
  2. 緩存機制的影響

    • Integer 的緩存范圍是 -128 ~ 127,超出范圍會創建新對象。
    • 可以通過 JVM 參數(如 -XX:AutoBoxCacheMax=512)調整緩存范圍。
  3. 比較操作的陷阱

    • 使用 == 比較引用類型時,可能會因為緩存或對象創建方式不同而導致結果不符合預期。
    • 推薦使用 equals 方法進行值比較。
  4. 性能問題

    • 頻繁的裝箱和拆箱操作會導致額外的對象創建和方法調用,影響性能。
    • 在性能敏感的場景下,盡量避免不必要的裝箱和拆箱。

擴展思考

在前面的分析中,我們提到 e == f 的結果為 false,因為 321 超出了 Integer 默認的緩存范圍(-128 ~ 127),導致每次調用 Integer.valueOf(321) 都會創建新的對象。然而,Java 提供了一種方式來擴展 Integer 的緩存范圍,從而改變這一行為。

如何調整緩存范圍
Integer 的緩存范圍可以通過 JVM 參數 -XX:AutoBoxCacheMax= 進行調整。例如,如果我們希望將緩存范圍擴展到 512,可以在啟動 JVM 時添加以下參數:

java -XX:AutoBoxCacheMax=512 Test

調整后的效果
當我們將緩存范圍擴展到 512 后,e == f 的結果會發生變化:

原因:321 現在位于緩存范圍內,因此 Integer.valueOf(321) 會返回緩存中的同一個對象。
輸出結果:true

底層原理分析
通過調整緩存范圍,Integer.valueOf 方法的行為發生了變化:

如果值在緩存范圍內(-128 ~ AutoBoxCacheMax),則返回緩存中的對象。
如果值超出緩存范圍,則創建新的 Integer 對象。
以下是 Integer.valueOf 方法的源碼片段:

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

其中,IntegerCache.low 和 IntegerCache.high 分別表示緩存范圍的下限和上限。默認情況下,IntegerCache.low = -128,IntegerCache.high = 127。通過 JVM 參數 -XX:AutoBoxCacheMax,我們可以動態調整 IntegerCache.high 的值。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80437.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80437.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80437.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何閱讀、學習 Linux 2 內核源代碼 ?

學習Linux 2內核源代碼是深入理解操作系統工作原理的絕佳途徑&#xff0c;但這無疑是一項極具挑戰性的任務。下面為你提供一套系統的學習方法和建議&#xff1a; 一、扎實基礎知識 操作系統原理 透徹掌握進程管理、內存管理、文件系統、設備驅動等核心概念。推薦閱讀《操作系…

樹莓派4的v4l2攝像頭(csi)no cameras available,完美解決

根據2025年最新技術文檔和樹莓派官方支持建議&#xff0c;no cameras available錯誤通常由驅動配置沖突或硬件連接問題導致。以下是系統化解決方案&#xff1a; 一、核心修復步驟 強制禁用傳統驅動 sudo nano /boot/firmware/config.txt確保包含以下配置&#xff08;2025年新版…

c++學習之路(3)

通過《c學習之路&#xff08;2&#xff09;》的學習&#xff0c;我們已經掌握了數據的儲存&#xff0c;以及數據的讀入與輸出&#xff0c;這次課程&#xff0c;我們要學習if語句的使用方法以及邏輯表達式請各位學者做好準備&#xff0c;謝謝配合&#xff01;&#xff01;&#…

Java程序題案例分析

目錄 一、基礎語法 1. 類與對象 2. 接口與抽象類 二、面向對象語法 1. 繼承與多態 2. 四種訪問修飾符 三、設計模式相關語法 一、策略模式&#xff08;接口回調實現&#xff09; 1. 完整實現與解析 二、工廠模式&#xff08;靜態工廠方法實現&#xff09; 1. 完整實…

comfyu BiRefNet-General模型下載及存放地方

https://huggingface.co/ZhengPeng7/BiRefNet/tree/main

HunyuanCustom:文生視頻框架論文速讀

《HunyuanCustom: A Multimodal-Driven Architecture for Customized Video Generation》論文講解 一、引言 本文提出了 HunyuanCustom&#xff0c;這是一個基于多模態驅動的定制化視頻生成框架。該框架旨在解決現有視頻生成模型在身份一致性&#xff08;identity consistenc…

tryhackme——Enumerating Active Directory

文章目錄 一、憑據注入1.1 RUNAS1.2 SYSVOL1.3 IP和主機名 二、通過Microsoft Management Console枚舉AD三、通過命令行net命令枚舉四、通過powershell枚舉 一、憑據注入 1.1 RUNAS 當獲得AD憑證<用戶名>:<密碼>但無法登錄域內機器時&#xff0c;runas.exe可幫助…

Web3 學習全流程攻略

目錄 ?? Web3 學習全流程攻略 ?? 第一階段:打好基礎(Web3 入門) ?? 目標: ?? 學習內容: ? 推薦資源: ????? 第二階段:技術棧搭建(成為 Web3 開發者) ?? 目標: ?? 學習內容: ? 推薦資源: ?? 第三階段:構建完整 DApp(去中心化應用)…

Python程序打包為EXE文件的全面指南

Python程序打包為EXE文件的全面指南 Python程序打包為EXE文件是解決程序分發和環境依賴問題的有效方法。通過將Python腳本及其所有依賴項整合為單一可執行文件&#xff0c;用戶無需安裝Python解釋器即可直接運行程序&#xff0c;極大提升了應用的便攜性和用戶體驗。本文將深入…

22、城堡防御工事——React 19 錯誤邊界與監控

一、魔法護盾&#xff1a;錯誤邊界機制 1. 城墻結界&#xff08;Error Boundary&#xff09; // 客戶端錯誤邊界use client function useErrorBoundary() {const [error, setError] useState(null);?const handleError useCallback((error, errorInfo) > {setError(erro…

深入理解 Istio 的工作原理 v1.26.0

解讀最新版本的 Istio 源碼確實是一項龐大的工程&#xff0c;但我可以為你梳理出一個清晰的脈絡&#xff0c;并指出關鍵模塊和代碼路徑&#xff0c;幫助你深入理解 Istio 的工作原理。 我們主要關注 Istio 的核心組件 Istiod 和數據平面的 Envoy Proxy。 前提&#xff1a; Go…

Flask 調試的時候進入main函數兩次

在 Flask 開啟 Debug 模式時&#xff0c;程序會因為自動重載&#xff08;reloader&#xff09;的機制而啟動兩個進程&#xff0c;導致if __name__ __main__底層的程序代碼被執行兩次。以下說明其原理與常見解法。 Flask Debug 模式下自動重載機制 Flask 使用的底層服務器 Wer…

CSS--圖片鏈接垂直居中展示的方法

原文網址&#xff1a;CSS--圖片鏈接垂直居中展示的方法-CSDN博客 簡介 本文介紹CSS圖片鏈接垂直居中展示的方法。 圖片鏈接 問題復現 源碼 <html xml:lang"cn" lang"cn"><head><meta http-equiv"Content-Type" content&quo…

雷賽伺服L7-EC

1電子齒輪比&#xff1a; 0x608F-01 只讀&#xff0c;編碼器圈脈沖【0x20000】【131072】 //Er1B1齒輪比錯誤 ----------------------------------- 0x6092-01 圈脈沖 //重新使能生效【pa008必須是0】值越小&#xff0c;轉的越多 -----------------------…

在js中大量接口調用并發批量請求處理器

并發批量請求處理器 ? 設計目標 該類用于批量異步請求處理&#xff0c;支持&#xff1a; 自定義并發數請求節拍控制&#xff08;延時&#xff09;失敗重試機制進度回調通知 &#x1f527; 構造函數參數 new BulkRequestHandler({dataList, // 要處理的數據列表r…

K8S擴縮容及滾動更新和回滾

目錄&#xff1a; 1、滾動更新1、定義Deployment配置2、應用更新 2、版本回滾1. 使用kubectl rollout undo命令 3、更新暫停與恢復1、暫停更新2、更新鏡像&#xff08;例如&#xff0c;使用kubectl set image命令&#xff09;3、恢復更新 4、彈性擴縮容1、擴容命令2、縮容命令3…

力扣-24.兩兩交換鏈表中的結點

題目描述 給你一個鏈表&#xff0c;兩兩交換其中相鄰的節點&#xff0c;并返回交換后鏈表的頭節點。你必須在不修改節點內部的值的情況下完成本題&#xff08;即&#xff0c;只能進行節點交換&#xff09;。 class Solution { public:ListNode* swapPairs(ListNode* head) {i…

對遺傳算法思想的理解與實例詳解

目錄 一、概述 二、實例詳解 1&#xff09;問題描述與分析 2&#xff09;初始化種群 3&#xff09;計算種群適應度 4&#xff09;遺傳操作 5&#xff09;基因交叉操作 6&#xff09;變異操作 三、計算結果 四、總結 一、概述 遺傳算法在求解最優解的問題中最為常用&a…

計算機圖形學編程(使用OpenGL和C++)(第2版) 學習筆記 07.光照

1. 光照 1.1. 光源 光源類型特點優點缺點環境光整個場景均勻受光&#xff0c;無方向和位置。模擬全局光照&#xff0c;避免完全黑暗的區域。缺乏方向性和真實感&#xff0c;無法產生陰影。平行光光線方向平行&#xff0c;無位置&#xff0c;僅有方向。計算簡單&#xff0c;適…

Python在大數據機器學習模型的多模態融合:深入探索與實踐指南

一、多模態融合的全面概述 1.1 多模態融合的核心概念 多模態融合(Multimodal Fusion)是指將來自不同傳感器或數據源(如圖像、文本、音頻、視頻、傳感器數據等)的信息進行有效整合,以提升機器學習模型的性能和魯棒性。在大數據環境下,多模態融合面臨著獨特的挑戰和機遇: 數…