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.mzph.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)是指将来自不同传感器或数据源(如图像、文本、音频、视频、传感器数据等)的信息进行有效整合,以提升机器学习模型的性能和鲁棒性。在大数据环境下,多模态融合面临着独特的挑战和机遇: 数…