Java 装箱与拆箱详解及实例代码
Java装箱与拆箱详解
前言:
要理解装箱和拆箱的概念,就要理解Java数据类型
装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。int包装成Integer、float包装成Float
拆箱:和装箱相反,将引用类型的对象简化成值类型的数据
Integera=100;这是自动装箱(编译器调用的是staticIntegervalueOf(inti)) intb=newInteger(100);这是自动拆箱
看下面一段代码
m1
publicclassDataType{ publicstaticvoidmain(Stringargs[]){ DataTypedt=newDataType(); dt.m11(); dt.m12(); } publicvoidm11(){ Integera=newInteger(100); Integerb=100; System.out.println("m11result"+(a==b)); } publicvoidm12(){ Integera=newInteger(128); Integerb=128; System.out.println("m12result"+(a==b)); } }
打印结果是什么?
m11resultfalse m12resultfalse
“==”比较的是地址,而a和b两个对象的地址不同,即是两个对象,所以都是false
通过javap解析字节码,内容如下
publicvoidm11(); Code: 0:new#44;//classjava/lang/Integer 3:dup 4:bipush100 6:invokespecial#46;//Methodjava/lang/Integer."<init>":(I)V 9:astore_1 10:bipush100 12:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 15:astore_2 16:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 19:new#59;//classjava/lang/StringBuilder 22:dup 23:ldc#61;//Stringm11result 25:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 28:aload_1 29:aload_2 30:if_acmpne37 33:iconst_1 34:goto38 37:iconst_0 38:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 41:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 44:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 47:return publicvoidm12(); Code: 0:new#44;//classjava/lang/Integer 3:dup 4:sipush128 7:invokespecial#46;//Methodjava/lang/Integer."<init>":(I)V 10:astore_1 11:sipush128 14:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 17:astore_2 18:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 21:new#59;//classjava/lang/StringBuilder 24:dup 25:ldc#82;//Stringm12result 27:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 30:aload_1 31:aload_2 32:if_acmpne39 35:iconst_1 36:goto40 39:iconst_0 40:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 43:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 46:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 49:return </init></init></init></init>
m2
publicclassDataType{ publicstaticvoidmain(Stringargs[]){ DataTypedt=newDataType(); dt.m21(); dt.m22(); } publicvoidm21(){ Integera=newInteger(100); Integerb=newInteger(100); System.out.println("m21result"+(a==b)); } publicvoidm22(){ Integera=newInteger(128); Integerb=newInteger(128); System.out.println("m22result"+(a==b)); } }
打印结果是
m21resultfalse m22resultfalse
a和b仍是两个对象
javap解析内容
publicvoidm21(); Code: 0:new#44;//classjava/lang/Integer 3:dup 4:bipush100 6:invokespecial#46;//Methodjava/lang/Integer."<init>":(I)V 9:astore_1 10:new#44;//classjava/lang/Integer 13:dup 14:bipush100 16:invokespecial#46;//Methodjava/lang/Integer."<init>":(I)V 19:astore_2 20:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 23:new#59;//classjava/lang/StringBuilder 26:dup 27:ldc#84;//Stringm21result 29:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 32:aload_1 33:aload_2 34:if_acmpne41 37:iconst_1 38:goto42 41:iconst_0 42:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 45:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 48:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 51:return publicvoidm22(); Code: 0:new#44;//classjava/lang/Integer 3:dup 4:sipush128 7:invokespecial#46;//Methodjava/lang/Integer."<init>":(I)V 10:astore_1 11:new#44;//classjava/lang/Integer 14:dup 15:sipush128 18:invokespecial#46;//Methodjava/lang/Integer."<init>":(I)V 21:astore_2 22:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 25:new#59;//classjava/lang/StringBuilder 28:dup 29:ldc#86;//Stringm22result 31:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 34:aload_1 35:aload_2 36:if_acmpne43 39:iconst_1 40:goto44 43:iconst_0 44:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 47:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 50:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 53:return
m3
publicclassDataType{ publicstaticvoidmain(Stringargs[]){ DataTypedt=newDataType(); dt.m31(); dt.m32(); } publicvoidm31(){ Integera=100; Integerb=100; System.out.println("m31result"+(a==b)); } publicvoidm32(){ Integera=128; Integerb=128; System.out.println("m32result"+(a==b)); } }
打印结果
m31resulttrue m32resultfalse
为什么有第一个是true,第二个是false呢?观察javap解析的数据
javap解析内容
publicvoidm31(); Code: 0:bipush100 2:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 5:astore_1 6:bipush100 8:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 11:astore_2 12:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 15:new#59;//classjava/lang/StringBuilder 18:dup 19:ldc#88;//Stringm31result 21:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 24:aload_1 25:aload_2 26:if_acmpne33 29:iconst_1 30:goto34 33:iconst_0 34:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 37:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 40:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 43:return publicvoidm32(); Code: 0:sipush128 3:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 6:astore_1 7:sipush128 10:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 13:astore_2 14:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 17:new#59;//classjava/lang/StringBuilder 20:dup 21:ldc#90;//Stringm32result 23:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 26:aload_1 27:aload_2 28:if_acmpne35 31:iconst_1 32:goto36 35:iconst_0 36:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 39:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 42:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 45:return
m4
publicclassDataType{ publicstaticvoidmain(Stringargs[]){ DataTypedt=newDataType(); dt.m41(); dt.m42(); } publicvoidm41(){ Integera=Integer.valueOf(100); Integerb=100; System.out.println("m41result"+(a==b)); } publicvoidm42(){ Integera=Integer.valueOf(128); Integerb=128; System.out.println("m42result"+(a==b)); } }
打印结果
m41resulttrue m42resultfalse
javap解析内容
publicvoidm41(); Code: 0:bipush100 2:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 5:astore_1 6:bipush100 8:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 11:astore_2 12:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 15:new#59;//classjava/lang/StringBuilder 18:dup 19:ldc#92;//Stringm41result 21:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 24:aload_1 25:aload_2 26:if_acmpne33 29:iconst_1 30:goto34 33:iconst_0 34:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 37:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 40:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 43:return publicvoidm42(); Code: 0:sipush128 3:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 6:astore_1 7:sipush128 10:invokestatic#49;//Methodjava/lang/Integer.valueOf:(I)Ljava/lang/In teger; 13:astore_2 14:getstatic#53;//Fieldjava/lang/System.out:Ljava/io/PrintStream; 17:new#59;//classjava/lang/StringBuilder 20:dup 21:ldc#94;//Stringm42result 23:invokespecial#63;//Methodjava/lang/StringBuilder."<init>":(Ljava/la ng/String;)V 26:aload_1 27:aload_2 28:if_acmpne35 31:iconst_1 32:goto36 35:iconst_0 36:invokevirtual#66;//Methodjava/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 39:invokevirtual#70;//Methodjava/lang/StringBuilder.toString:()Ljava/l ang/String; 42:invokevirtual#74;//Methodjava/io/PrintStream.println:(Ljava/lang/St ring;)V 45:return }
分析
javap是Java自带的一个工具,可以反编译,也可以查看Java编译器生成的字节码(上面代码只使用了javap-cDataType),是分析代码的一个好工具,具体怎么使用请Google一下
先看一下m4,为什么运行结果中出现了“true”呢,true说明a、b是同一个对象。
但a对象是调用Integer.valueOf()生成的,b是通过自动装箱生成的对象,为什么会是同一个对象呢?再看一下字节码吧,毕竟Java程序是依靠虚拟机运行字节码实现的。
m41这个方法只适用了一次valueOf(),但字节码中出现了两次,说明自动装箱时也调用了valueOf()。
下面是valueOf()具体实现
/** *Returnsa<tt>Integer</tt>instancerepresentingthespecified *<tt>int</tt>value. *Ifanew<tt>Integer</tt>instanceisnotrequired,thismethod *shouldgenerallybeusedinpreferencetotheconstructor *{@link#Integer(int)},asthismethodislikelytoyield *significantlybetterspaceandtimeperformancebycaching *frequentlyrequestedvalues. * *@paramian<code>int</code>value. *@returna<tt>Integer</tt>instancerepresenting<tt>i</tt>. *@since1.5 */ publicstaticIntegervalueOf(inti){ finalintoffset=128; if(i>=-128&&i<=127){//mustcache returnIntegerCache.cache[i+offset]; } returnnewInteger(i); }
在【-128,127】之间的数字,valueOf返回的是缓存中的对象,所以两次调用返回的是同一个对象。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!