Java 装箱与拆箱详解
前言:
要理解装箱和拆箱的概念,就要理解Java数据类型
装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。int包装成Integer、float包装成Float
拆箱:和装箱相反,将引用类型的对象简化成值类型的数据
Integer a = 100; 这是自动装箱 (编译器调用的是static Integer valueOf(int i)) int b = new Integer(100); 这是自动拆箱
看下面一段代码
m1
public class DataType { public static void main(String args[]) { DataType dt = new DataType(); dt.m11(); dt.m12(); } public void m11() { Integer a = new Integer(100); Integer b = 100; System.out.println("m11 result " + (a == b)); } public void m12() { Integer a = new Integer(128); Integer b = 128; System.out.println("m12 result " + (a == b)); } }
打印结果是什么?
m11 result false m12 result false
“==”比较的是地址,而a和b两个对象的地址不同,即是两个对象,所以都是false
通过javap解析字节码,内容如下
public void m11(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: bipush 100 6: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 9: astore_1 10: bipush 100 12: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 15: astore_2 16: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 19: new #59; //class java/lang/StringBuilder 22: dup 23: ldc #61; //String m11 result 25: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 28: aload_1 29: aload_2 30: if_acmpne 37 33: iconst_1 34: goto 38 37: iconst_0 38: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 41: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 44: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 47: return public void m12(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: sipush 128 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 10: astore_1 11: sipush 128 14: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 17: astore_2 18: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 21: new #59; //class java/lang/StringBuilder 24: dup 25: ldc #82; //String m12 result 27: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 30: aload_1 31: aload_2 32: if_acmpne 39 35: iconst_1 36: goto 40 39: iconst_0 40: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 43: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 46: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 49: return </init></init></init></init>
m2
public class DataType { public static void main(String args[]) { DataType dt = new DataType(); dt.m21(); dt.m22(); } public void m21() { Integer a = new Integer(100); Integer b = new Integer(100); System.out.println("m21 result " + (a == b)); } public void m22() { Integer a = new Integer(128); Integer b = new Integer(128); System.out.println("m22 result " + (a == b)); } }
打印结果是
m21 result false m22 result false
a和b仍是两个对象
javap解析内容
public void m21(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: bipush 100 6: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 9: astore_1 10: new #44; //class java/lang/Integer 13: dup 14: bipush 100 16: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 19: astore_2 20: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 23: new #59; //class java/lang/StringBuilder 26: dup 27: ldc #84; //String m21 result 29: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 32: aload_1 33: aload_2 34: if_acmpne 41 37: iconst_1 38: goto 42 41: iconst_0 42: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 45: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 48: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 51: return public void m22(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: sipush 128 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 10: astore_1 11: new #44; //class java/lang/Integer 14: dup 15: sipush 128 18: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 21: astore_2 22: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 25: new #59; //class java/lang/StringBuilder 28: dup 29: ldc #86; //String m22 result 31: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 34: aload_1 35: aload_2 36: if_acmpne 43 39: iconst_1 40: goto 44 43: iconst_0 44: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 47: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 50: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 53: return
m3
public class DataType { public static void main(String args[]) { DataType dt = new DataType(); dt.m31(); dt.m32(); } public void m31() { Integer a = 100; Integer b = 100; System.out.println("m31 result " + (a == b)); } public void m32() { Integer a = 128; Integer b = 128; System.out.println("m32 result " + (a == b)); } }
打印结果
m31 result true m32 result false
为什么有第一个是true,第二个是false呢?观察javap解析的数据
javap解析内容
public void m31(); Code: 0: bipush 100 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 5: astore_1 6: bipush 100 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 11: astore_2 12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 15: new #59; //class java/lang/StringBuilder 18: dup 19: ldc #88; //String m31 result 21: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 24: aload_1 25: aload_2 26: if_acmpne 33 29: iconst_1 30: goto 34 33: iconst_0 34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 43: return public void m32(); Code: 0: sipush 128 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 6: astore_1 7: sipush 128 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 13: astore_2 14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 17: new #59; //class java/lang/StringBuilder 20: dup 21: ldc #90; //String m32 result 23: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 26: aload_1 27: aload_2 28: if_acmpne 35 31: iconst_1 32: goto 36 35: iconst_0 36: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 45: return
m4
public class DataType { public static void main(String args[]) { DataType dt = new DataType(); dt.m41(); dt.m42(); } public void m41() { Integer a = Integer.valueOf(100); Integer b = 100; System.out.println("m41 result " + (a == b)); } public void m42() { Integer a = Integer.valueOf(128); Integer b = 128; System.out.println("m42 result " + (a == b)); } }
打印结果
m41 result true m42 result false
javap解析内容
public void m41(); Code: 0: bipush 100 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 5: astore_1 6: bipush 100 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 11: astore_2 12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 15: new #59; //class java/lang/StringBuilder 18: dup 19: ldc #92; //String m41 result 21: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 24: aload_1 25: aload_2 26: if_acmpne 33 29: iconst_1 30: goto 34 33: iconst_0 34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 43: return public void m42(); Code: 0: sipush 128 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 6: astore_1 7: sipush 128 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 13: astore_2 14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 17: new #59; //class java/lang/StringBuilder 20: dup 21: ldc #94; //String m42 result 23: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 26: aload_1 27: aload_2 28: if_acmpne 35 31: iconst_1 32: goto 36 35: iconst_0 36: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 45: return }
分析
javap是Java自带的一个工具,可以反编译,也可以查看Java编译器生成的字节码(上面代码只使用了javap -c DataType),是分析代码的一个好工具,具体怎么使用请Google一下
先看一下m4,为什么运行结果中出现了“true”呢,true说明a、b是同一个对象。
但a对象是调用Integer.valueOf()生成的,b是通过自动装箱生成的对象,为什么会是同一个对象呢?再看一下字节码吧,毕竟Java程序是依靠虚拟机运行字节码实现的。
m41这个方法只适用了一次valueOf(),但字节码中出现了两次,说明自动装箱时也调用了valueOf()。
下面是valueOf()具体实现
/** * Returns a <tt>Integer</tt> instance representing the specified * <tt>int</tt> value. * If a new <tt>Integer</tt> instance is not required, this method * should generally be used in preference to the constructor * {@link #Integer(int)}, as this method is likely to yield * significantly better space and time performance by caching * frequently requested values. * * @param i an <code>int</code> value. * @return a <tt>Integer</tt> instance representing <tt>i</tt>. * @since 1.5 */ public static Integer valueOf(int i) { final int offset = 128; if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); }
在【-128,127】之间的数字,valueOf返回的是缓存中的对象,所以两次调用返回的是同一个对象。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
更多Java 装箱与拆箱详解及实例代码相关文章请关注PHP中文网!

JVMmanagesgarbagecollectionacrossplatformseffectivelybyusingagenerationalapproachandadaptingtoOSandhardwaredifferences.ItemploysvariouscollectorslikeSerial,Parallel,CMS,andG1,eachsuitedfordifferentscenarios.Performancecanbetunedwithflagslike-XX:NewRa

Java代码可以在不同操作系统上无需修改即可运行,这是因为Java的“一次编写,到处运行”哲学,由Java虚拟机(JVM)实现。JVM作为编译后的Java字节码与操作系统之间的中介,将字节码翻译成特定机器指令,确保程序在任何安装了JVM的平台上都能独立运行。

Java程序的编译和执行通过字节码和JVM实现平台独立性。1)编写Java源码并编译成字节码。2)使用JVM在任何平台上执行字节码,确保代码的跨平台运行。

Java性能与硬件架构密切相关,理解这种关系可以显着提升编程能力。 1)JVM通过JIT编译将Java字节码转换为机器指令,受CPU架构影响。 2)内存管理和垃圾回收受RAM和内存总线速度影响。 3)缓存和分支预测优化Java代码执行。 4)多线程和并行处理在多核系统上提升性能。

使用原生库会破坏Java的平台独立性,因为这些库需要为每个操作系统单独编译。1)原生库通过JNI与Java交互,提供Java无法直接实现的功能。2)使用原生库增加了项目复杂性,需要为不同平台管理库文件。3)虽然原生库能提高性能,但应谨慎使用并进行跨平台测试。

JVM通过JavaNativeInterface(JNI)和Java标准库处理操作系统API差异:1.JNI允许Java代码调用本地代码,直接与操作系统API交互。2.Java标准库提供统一API,内部映射到不同操作系统API,确保代码跨平台运行。

modularitydoesnotdirectlyaffectJava'splatformindependence.Java'splatformindependenceismaintainedbytheJVM,butmodularityinfluencesapplicationstructureandmanagement,indirectlyimpactingplatformindependence.1)Deploymentanddistributionbecomemoreefficientwi

BytecodeinJavaistheintermediaterepresentationthatenablesplatformindependence.1)Javacodeiscompiledintobytecodestoredin.classfiles.2)TheJVMinterpretsorcompilesthisbytecodeintomachinecodeatruntime,allowingthesamebytecodetorunonanydevicewithaJVM,thusfulf


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

记事本++7.3.1
好用且免费的代码编辑器