Java自动拆箱和装箱

深入理解Java的自动装箱与拆箱:原理、性能及常见坑点详解 自动装箱:指的是基本数据类型自动转换成对应的包装类。例如,将int转换为Integer。自动拆箱:指的是包装类自动转换成对应的基本数据类型。例如,将Integer转换为int。从Java 5开始,编译器自动执行这些转换,使得代码更简洁,减少了显式转换的代码量。基本数据类型包装类byteByteshortShortintIntegerlongLongfloatFloatdoubleDoublecharBoolean。 阅读详情

什么是自动拆箱和装箱

定义

  • 自动装箱就是 Java 自动将原始数据类型转为对应的包装类对象 比如将 int 型的变量转成 Integer对象 自动拆箱反之(从 Java 1.5 开始引入)

过程

  • 自动装箱时,编译器调用 valueOf() 将原始数据类型值转为对象;同时自动拆箱时,编译器调用类似 intValue(), doubleValue() 这类方法将对象转换成原始类型值
基本类型 大小 数值范围 默认值 包装类型
boolean ^ true,false false Boolean
byte 8bit -2^7 – 2^7-1 0 Byte
char 16bit \u0000 – \uffff \u0000 Character
short 16bit -2^15 – 2^15-1 0 Short
int 32bit -2^31 – 2^31-1 0 Integer
long 64bit -2^63 – 2^63-1 0 Long
float 32bit IEEE 754 0.0f Float
double 64bit IEEE 754 0.0d Double
void ^ ^ ^ Void

基本类型与装箱基本类型的区别

  • 基本类型只有值,而装箱基本类型则具有与它们的值不同的同一性。换句话说,对装箱基本类型运用 == 操作符几乎总是错的

  • 基本类型只有功能完备的值,而装箱基本类型除了它对应基本类型的所有功能值外,还有一个非功能值 null,这导致了对于包装基本类型进行拆箱操作后所进行的操作存在 NPE 的风险

  • 基本类型更加省空间和时间,如果对包装类型进行频繁的装箱和拆箱操作会影响性能

何时发生自动装箱与拆箱?

赋值时

  • 在Java1.5之前,需要手动地进行类型转换,而现在所有的转换都是有编译器来完成
//before autoboxing
Integer iObject = Integer.valueOf(3);
int iPrimitive = iObject.intValue()

//after java5
Integer iObject = 3;      //autobxing - primitive to wrapper conversion
int iPrimitive = iObject; //unboxing - object to primitive conversion
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

方法调用时

  • 当在进行方法调用时,可以传入原始数据值或对象,编译器同样会自动进行转换
public static Integer show(Integer iParam){
   System.out.println("autoboxing example - method invocation i: " + iParam);
   return iParam;
}

//autoboxing and unboxing in method invocation
show(3); //autoboxing
int result = show(3); //unboxing because return type of method is Integer
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

自动装箱引起的性能问题

  • 如果有人告诉你:“只要修改一个字符,下面这段代码的运行速度就能提高5倍。”,你觉得可能么?
long t = System.currentTimeMillis();
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
    sum += i;
}
System.out.println("total:" + sum);
System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms");
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 输出结果:

total:2305843005992468481 
processing time: 63556 ms

  • 将Long修改为long,再来看一下运行结果
long t = System.currentTimeMillis();
long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
    sum += i;
}
System.out.println("total:" + sum);
System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms");
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 输出结果:

total:2305843005992468481 
processing time: 12229 ms

  • 事实证明,仅仅修改了一个字符,性能提高了不止一倍两倍。那,就究竟是什么原因导致的呢? 
    因为,+这个操作符不适用Integer对象,在进行数值相加操作之前会发生自动拆箱操作,转换成int,相加之后还会发生自动拆箱操作,装换成Integer对象。其内部变化如下:
sum = sum.longValue() + i;
Long sum = new Long(sum);
   
  • 1
  • 2
  • 1
  • 2
  • 很明显,在上面的循环中会创建2147483647个”Long“类型实例,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量

说明:包含在包装器中的内容不会改变。即Long对象是不可变的

重载与自动装箱

  • 在java 5之前,value(int)和value(Integer)是完全不相同的方法,开发者不会因为传入是int还是Integer调用哪个方法困惑,但是由于自动装箱和拆箱的引入,处理重载方法时会不会有什么变化呢?可通过下面一个例子进行探讨:
public void test(int num){
    System.out.println("method with primitive argument");
}
public void test(Integer num){
    System.out.println("method with wrapper argument");
}
//calling overloaded method
AutoboxingTest autoTest = new AutoboxingTest();
int value = 3;
autoTest.test(value);  //no autoboxing 
Integer iValue = value;
autoTest.test(iValue); //no autoboxing
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 输出结果

method with primitive argument 
method with wrapper argument

  • 从输出结果可以看出,在重载的情况下,不会发生自动装箱操作

注意事项

  • 自动装箱与拆箱在编程过程中给我们带来了极大的方便,但也存在一些容易让人出错的问题

对象相等比较

  • “==”既可用于原始值的比较,也可用于对象间的比较。当进行对象间的比较时,实质上比较的是对象的引用是否相等,而不是比较对象代表的值。如果要比较对象的值,应当使用对象对应的equals方法。可通过以下例子进行探讨:
public class AutoboxingTest {
    public static void main(String args[]) {
        // Example 1: == comparison pure primitive – no autoboxing
        int i1 = 1;
        int i2 = 1;
        System.out.println("i1==i2 : " + (i1 == i2)); // true

        // Example 2: equality operator mixing object and primitive
        Integer num1 = 1; // autoboxing
        int num2 = 1;
        System.out.println("num1 == num2 : " + (num1 == num2)); // true

        // Example 3: special case - arises due to autoboxing in Java
        Integer obj1 = 1; // autoboxing will call Integer.valueOf()
        Integer obj2 = 1; // same call to Integer.valueOf() will return same cached Object
        System.out.println("obj1 == obj2 : " + (obj1 == obj2)); // true

        // Example 4: equality operator - pure object comparison
        Integer one = new Integer(1); // no autoboxing
        Integer anotherOne = new Integer(1);
        System.out.println("one == anotherOne : " + (one == anotherOne)); // false
    }
}
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 输出结果

i1==i2 : true 
num1 == num2 : true 
obj1 == obj2 : true 
one == anotherOne : false

  • 值得注意的是,在Example 2中,比较是一个对象和一个原始值,出现这种情况比较的应该是对象的值

  • 让人感到困惑的Example 3,在一开始我们说过,”==”用于对象间的比较时,比较的是它们的引用,那么为什么obj1 == obj2返回的结果却是true?这是一种极端情况,处于节省内存的考虑,JVM会缓存-128到127的Integer对象。也就是说,在创建obj1对象时,会进行自动装箱操作,并且将其对象保存至缓存中,在创建obj2对象时,同样会进行自动装箱操作,然后在缓存中查找是否有相同值的对象,如果有,那么obj2对象就会指向obj1对象。obj1和obj2实际上是同一个对象。所以使用”==”比较返回true

  • 而Example 4,是通过使用构造器来创建对象的,而没有发生自动装箱操作,不会执行缓存策略,故one和anotherOne是指向不同的引用的

 说明:这种 Integer 缓存策略仅在自动装箱(autoboxing)的时候有用,使用构造器创建的 Integer 对象不能被缓存

容易混乱的对象和原始数据值

  • 一个很容易犯错的问题,就是忽略对象与原始数据值之间的差异,在进行比较操作时,对象如果没有初始化或者为null,在自动拆箱过程中obj.xxxValue,则会抛出NullPointerException,可通过以下例子进行探讨:
private static Integer count;
//NullPointerException on unboxing
if( count <= 0){
  System.out.println("Count is not started yet");
}
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

生成无用对象增加GC压力

  • 因为自动装箱会隐式地创建对象,像前面提到的那样,如果在一个循环体中,会创建无用的中间对象,这样会增加GC压力,拉低程序的性能。所以在写循环时一定要注意代码,避免引入不必要的自动装箱操作

参考资料

【原理图PCB专题】案例:双排0.5mm间距座子转单排0.5mm间距座子Layout方案分析 本文提供一种分析思路,并通过实际案例来进行Layout方案分析的讲解。 阅读详情

相关推荐

架构设计之架构治理

架构治理的本质是“用规则约束复杂性,用流程保障落地,用数据驱动优化”先定目标:明确量化的治理目标,避免盲目行动;立标准:建立覆盖分层、选型、接口、拆分的统一规范,奠定治理基础;强评审:通过架构评审把控设计环节,提前规避风险;全流程:将治理规则贯穿设计、开发、测试、部署、运维全生命周期;重保障:通过组织、流程、工具确保治理落地,而非“纸上谈兵”;持续迭代:随业务与技术演进优化治理规则,避免“一劳永逸”。

xiaolyuh的专栏 810

自动装箱与自动拆箱

什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。 自动装箱是java编译器在java原生类型和对应的对象包装类型上做的自动转换。 例如,把int 装换成 Integer double转换成Double等等。 如果是反过来转换,那么叫做自动拆箱,也是编译器为我们做的事情。 一般我们要创建一个类的对象实例的时候,我...

水逆呱的博客 2412

工业以太网通讯Profinet协议详解

Profinet是通过西门子控制系统被广泛使用的工业通信协议,是一种较新的,基于以太网的工业通讯协议。

mydatai的专栏 8852

【学习Day11】什么是自动装箱和自动拆箱,什么时候下应该避免自动拆装箱?

装箱操作就是把基础数据类型自动转换成引用类型,比如定义一个数值类型它自动把int类型的数字转换为对应的引用类型,这就是装箱操作。拆箱操作就是把引用类型转换为对应的基础类型,比如这个num变量赋值给这就是拆箱操作。根据以上内容分析,基础数据类型和封装类。

weixin_44382688的博客 2733

电力电子技术文章:ACOT控制模式在Buck变换器中的频率稳定性分析

本文深入分析了ACOT控制模式在Buck变换器中实现频率稳定性的原理与优势。通过对比传统COT模式,阐述了ACOT如何通过自适应调整导通时间,将开关频率锁定在设定值,从而有效应对输入电压与负载变化。文章还探讨了其在轻载DCM模式下的高效与平滑切换特性,并提供了关键的设计考量与实战指南。

cc789的博客 1150

MindIE与vLLM-Ascend性能对决:Qwen3在昇腾910B上的推理效率实测

本文深度对比了昇腾910B平台上两大推理框架MindIE与vLLM-Ascend的性能表现。通过实测Qwen3系列模型,详细分析了二者在单卡、多卡场景下的推理效率、扩展性及生产环境适用性,为AI算力基础设施选型提供关键参考。

weixin_29214335的博客 1184

自动拆箱与装箱

对Java中的自动拆箱与装箱进行详细分析

AI+全栈,AI+应用,实操落地,前沿技术 1302

Jitsi中的Prosody(谐音:破扫敌)介绍

凭借其灵活的插件系统、强大的安全性和出色的性能,Prosody 成为许多企业和开发者构建定制化通信解决方案的首选。在 Jitsi 的多方视频会议场景中,Prosody 不仅处理基本的信令任务,还需要与其他组件(如 Jitsi Videobridge)协作,确保视频流的正确分发和控制。Prosody 提供了丰富的插件系统,允许开发者通过模块扩展其功能。Prosody 就是一个实现 XMPP 协议的服务器,它支持 XMPP 协议的标准功能,如消息传递、群组聊天、传送状态信息等,并提供了高效、可扩展的服务。

江左散人的专栏 1166

【Java】Java 中的自动装箱和拆箱

自动装箱和拆箱可以让开发人员编写更加清晰的代码,使代码更加易于阅读。基本类型包装类型booleanBooleanbyteBytecharCharacterfloatFloatintIntegerlongLongshortShortdoubleDouble自动装箱和拆箱的实现是通过 Java 编译器在编译时进行的。具体来说,Java 编译器会将自动装箱和拆箱操作转换为对应的方法调用,以实现基本数据类型和包装类型之间的转换。但这在性能方面是要付出代价的。

swadian2008的博客 6581

HDMI2.1/eDP TX接口设计:

HDMI2.1向下兼容,HDMI2.1工作在FRL模式,HDMI2.0工作在TMDS模式。因此采用AC耦合电压模式驱动器。一般采用220nF,封装建议0201。,但是协议要求,往 CEC 管脚通过 27K 电阻加 3.3V 电压,漏电不允许超过。NOTE:如果只需要支持 HDMI2.0 及以下模式时, MOS管也不能省掉。DDC_SCL/DDC_SDA 协议规定是。HDMI2.0模式:配置为高,MOS导通。HDMI2.1模式:配置为低,MOS不导通。,必须增加电平转换电路。形成直流偏置,大约3V。

qq_40010777的博客 7858

自绘CListCtrl时发现ON_WM_MEASUREITEM_REFLECT和DrawItem(LPDRAWITEMSTRUCT lpMeasureItemStruct) 无响应

自绘CListCtrl时发现ON_WM_MEASUREITEM_REFLECT和DrawItem(LPDRAWITEMSTRUCT lpMeasureItemStruct) 无响应 一般情况下,我们都是在 dialog 里面 放一个 list 控件,然后 用自己的类绑定自己的自绘对象,如同下面: 1.  在 dialog 里面 加一个 list 列表 2. 然后 绑定这个列表 哈哈...

mfreesky的专栏 2170

Java的自动装箱和自动拆箱

在Java开发中,自动装箱(Autoboxing)和自动拆箱(Unboxing)是指基本数据类型与其对应的包装类之间的自动转换。这些特性可以使代码更加简洁和易读,但在实际项目中也带来了某些潜在的问题。本文将详细介绍自动装箱和拆箱的概念,并探讨在Spring Boot项目开发和Bean转换中的应用与注意事项。

常备不懈 2730

Aurix TC3xx系列MCU DMA模块配置方法(二)

本文主要基于英飞凌Aurix TC3xx系列MCU,通过EB tresos配置工具,介绍DMA驱动模块的配置方法。

m0_38045338的博客 2850

java装箱和拆箱的意义_Java自动装箱/拆箱

在 让人疑惑的Java代码 一文中我们说到编译器自动为我们加上valueOf这个方法吗?忘了没关系,我们来回顾一下,源代码如下:编译一下,拿到class文件,我们反编译一下,变成了如下代码:这个加上valueOf方法的过程,就是Java中经常说的装箱过程。Java中一共有四类八种基本数据类型,除掉这几种类型,其它的都是对象,也就是引用类型。在JDK1.5中,给这四类八种基本类型加入了包装类,对应如...

weixin_42299494的博客 1611

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

java-自动装箱和自动拆箱

一、简述   自动装箱和自动拆箱是两个相反的过程,自动装箱即将基本数据类型转换为对应的封装类,自动拆箱即将封装类转换为对应的基本数据类型。此外,装箱的过程会增加内存的消耗,影响性能,因为这个过程会创建对应的对象。   可进行自动装箱和自动拆箱的类型如下图所示: 二、自动装箱和自动拆箱   采用如下示例说明自动装箱和自动拆箱的原理。 public class Main { public static void main(String[] args) { Integer integer

weixin_41427129的博客 1561

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

如何理解Java中的自动拆箱和自动装箱?

小伟刚毕业时面的第一家公司就被面试官给问住了,记忆尤深啊… 如何理解Java中的自动拆箱和自动装箱? 自动拆箱?自动装箱?什么鬼,听都没听过啊,这…这…知识盲区… 回到家后小伟赶紧查资料,我透,这不就是问基本类型跟封装类型吗,面试官整啥名词呢… 别问结果,问就是没过。 1、 什么是自动装箱,自动拆箱 定义:基本数据类型和包装类之间可以自动地相互转换 理解:装箱就是自动将基本数据类型转换为封装类型,拆箱就是自动将封装类型转换为基本数据类型。 我们知道,Java中提供了四大类基本数据类型,分别是:整数、浮点数、

niceyoo的博客 2080

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【Java第8集】java自动装箱和拆箱详解

自动装箱将基本数据类型(如intdouble等)自动转换为对应的包装类对象(如IntegerDouble示例// 自动装箱:int → Integer自动拆箱将包装类对象自动转换为对应的基本数据类型。示例// 自动拆箱:Integer → int特性说明自动装箱等,调用valueOf()方法。自动拆箱等,调用intValue()方法。应用场景集合类、泛型、方法参数传递等。潜在问题性能开销、空指针异常、缓存池陷阱。最佳实践避免频繁拆装箱,显式处理 null,使用equals()比较对象。

学不可以已,活到老,学到老。 1365

有关java中的自动拆箱和装箱

JAVA中的自动拆箱和装箱 java中的自动拆箱和装箱是jdk1.5及之后的新特性,我一直没太理解是怎么一回事,最近抽空终于把它的相关知识点整理了一下。 首先让我们了解一下什么是Integer类,从Integer入手: Integer Integer 类在对象中包装了一个基本类型int的值。Integer类型的对象包含一个 int 类型的字段。此外,该类提供了多个方法,能在 int 类型和 Str...

qq_41040989的博客 341

java中什么是手动装箱、手动拆箱、自动装箱和自动拆箱以及128陷阱

通过 == 运算符比较它们的值,可以发现 a 和 b 的值相等,返回 true。使用 equals() 方法比较它们的值,结果都是 true ,因为 equals() 方法比较的是对象的值,而不是对象的地址。这是因为,在Integer的valueOf()方中,当数值在-128-127之间时,数值都存储在有一个catch数组当中,该数组相当于一个缓存,当我们在-128-127之间进行自动装箱的时候,我们就直接返回该值在内存当中的地址,所以在-128-127之间的数值用==进行比较是相等的。

qq_62636650的博客 1393

详解Java包装类的自动拆箱和装箱

详解Java包装类的自动拆箱和装箱

2301_77899321的博客 2003

java为什么要引入自动装箱和拆箱的功能?

Java 引入自动装箱和拆箱的功能,旨在简化代码中基本数据类型与包装类之间的转换,提升代码的可读性和简洁性。自动装箱和拆箱使得 Java 更加灵活,减少了开发者的工作量。然而,开发者在使用时应当注意性能开销和空指针异常等潜在问题。

qq_44082755的博客 946

Java自动装箱和拆箱

在进行自动装箱的过程中,Java编译器会自动调用valueOf()方法来实现基本类型的转换为对应的封装类型;Java编译器中自带的自动装箱和拆箱机制会将我们平时需要重复书写的、机械式的代码自动化完成,更加简洁清晰的代码也会极大地提升程序的可读性。将i赋值给j的时候,Java编译器会自动将i所引用的对象转换成一个int类型的值,并在内存中存储该值。这种转换也是程序员无需关注的。自动装箱和拆箱是Java中提供的一种方便而强大的功能,用户可以使用自动装箱和拆箱来转换基本数据类型与对应的封装类型。

qwert 1133

深入了解Java 自动装箱和自动拆箱

快速了解Java自动装箱和自动拆箱底层实现流程

DU9999999的博客 2143

java为什么要实现自动装箱和拆箱

虽然自动拆箱和装箱在某些场景下可能会引入轻微的性能开销(因为会创建额外的对象),但在大多数情况下,这种便利性是值得的。Java 开发者可以更专注于业务逻辑的实现,而无需过多关注基本数据类型和包装类型之间的显式转换。在 Java 早期版本中,基本数据类型和包装类之间的转换非常繁琐,需要手动进行。自动拆箱和装箱的引入极大地简化了这一过程。在 Java 早期版本中,基本数据类型和包装类之间的转换非常繁琐,需要手动进行。同样,自动拆箱简化了代码,使得对包装类型的操作更像基本数据类型的操作。类型的值放入一个需要。

2202_75439262的博客 1006

JAVA自动装箱和自动拆箱

众所周知,java是一门面向对象的编程语言,所以除了8大基础类型之外一切皆为对象,但为了方便面向对象开发,基础类型也有对应的包装类。但包装类和基础类型在赋值或比较时要进行类型转化,使用起来不够丝滑,感觉他们之间有很大的鸿沟。所以jdk1.5之后就推出了自动装箱和自动拆箱机制,使开发更加方便,代码更加简洁。自动装箱就是在编译时自动将基础类型转化与之对应的包装类,而自动拆箱刚好与之相反,就是在编译时自动将包装类转化为与之对应的基础类型。...

qq_42313904的博客 1658
上一篇: service与thread的区别
下一篇: Android studio用真机调试时logcat一直输出日志?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值