Java 装箱与拆箱详解及实例代码
程序员文章站
2024-03-08 12:35:34
java 装箱与拆箱详解
前言:
要理解装箱和拆箱的概念,就要理解java数据类型
装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。int包装成in...
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返回的是缓存中的对象,所以两次调用返回的是同一个对象。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!