Integer自动装箱细节分析
来源:互联网 发布:圣诞节淘宝网页设计 编辑:程序博客网 时间:2024/06/11 02:11
装箱 就是将基本的数据类型(比如int
)封装成对象类型(比如Integer
)。拆箱 就是将对象类型拆包装为基本类型。
装箱和拆箱操作为我们提供了很多便利。
- 包装类,如
Integer
给我们提供的友好的API
方法,使我们可以快速完成数据类型之间的转换。Java
是面向对象的,我们在Java
中处理的绝大多数都是对象,在类似Map
集合类等很多场合中,我们需要放入Integer
这种对象类型。
很多情况下,编译器为我们自动完成了基本数据类型的拆箱和装箱操作。
public class TestInteger{ public static void main(String[] args){ int a1 = 127; //auto-boxing Integer i = a1; //auto-unboxing int b1 = i; }}
下面,我们来看一段代码:
public class TestInteger{ public static void main(String[] args){ int a1 = 12; //auto-boxing Integer number1 = a1; Integer number2 = a1; System.out.println("number1==number2:"+ (number1==number2)); //out:number1==number2:true int b1=128; Integer number3 = b1; Integer number4 = b1; System.out.println("number3==number4:"+ (number3==number4)); //out:number3==number4:false }}
通过编译,我们发现Integer
类型在auto-boxing
操作时,-128到127之间的int
类型整数封装之后的对象是同一个,这个范围之外的int
类型整数封装之后对象是不同的。通过后面的分析,我们可以知道:
-128到127这个范围,-128是固定的,上限127是我们可以通过Jvm参数配置的。
为什么会这样呢?我们通过这段程序的字节码分析这段程序编译的细节:
Microsoft Windows [版本 10.0.15063](c) 2017 Microsoft Corporation。保留所有权利。D:\JavaProject\SuperMarket\bin\com\javaexc\service>javap -c Test.classCompiled from "Test.java"public class com.javaexc\service.Test { public com.javaexc\service.Test(); Code: 0: aload_0 1: invokespecial #8 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: bipush 12 2: istore_1 3: iload_1 4: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 7: astore_2 8: iload_1 9: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 12: astore_3 13: getstatic #22 // Field java/lang/System.out:Ljava/io/PrintStream; 16: new #28 // class java/lang/StringBuilder 19: dup 20: ldc #30 // String number1==number2: 22: invokespecial #32 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 25: aload_2 26: aload_3 27: if_acmpne 34 30: iconst_1 31: goto 35 34: iconst_0 35: invokevirtual #35 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 38: invokevirtual #39 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 41: invokevirtual #43 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 44: sipush 128 47: istore 4 49: iload 4 51: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 54: astore 5 56: iload 4 58: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 61: astore 6 63: getstatic #22 // Field java/lang/System.out:Ljava/io/PrintStream; 66: new #28 // class java/lang/StringBuilder 69: dup 70: ldc #48 // String number3==number4: 72: invokespecial #32 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 75: aload 5 77: aload 6 79: if_acmpne 86 82: iconst_1 83: goto 87 86: iconst_0 87: invokevirtual #35 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 90: invokevirtual #39 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 93: invokevirtual #43 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 96: return}
通过观察4、9、51、58这四行字节码我们发现,编译器调用
Integer.valueOf()
帮助我们完成自动装箱操作。
我们进一步阅读Integer.class
文件,分析Integer.valueOf()
实际上完成的工作:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
当输入参数i
满足i >= IntegerCache.low && i <= IntegerCache.high
这个范围时,return
的是IntegerCache.cache[]
这个数组里的元素,否则return
一个新的Integer
对象。
那么IntegerCache.low
和 IntegerCache.high
以及IntegerCache.cache[]
分别是什么呢?我们继续看代码:
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the -XX:AutoBoxCacheMax=<size> option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low)); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }
我们看到IntegerCache.low
和 IntegerCache.high
以及IntegerCache.cache[]
都是static final
修饰的,IntegerCache.low
固定是-128,IntegerCache.high
可以通过设置属性来修改,默认是127。
- 结论1:
int
类型整数自动装箱时,当值在上述范围内时,返回的是IntegerCache.cache[]
这个数组里的同一个元素。
这也就是-128到127之间的int
类型整数自动封装成同一个对象的原因。这里的IntegerCache
就是用来处理Integer
自动装箱操作的。
在自动装箱时,当值在new()
一个新的对象。这样便加大了对简单数字的重复使用,在某些场景下可以优化我们代码的性能。
- 结论2:
- 值得说明的是,上述情况只有在我们使用自动装箱时,编译器自动调用
Integer.valueOf()
才会出现,如果我们采用new()
来创建对象,每一次new()
的对象都是一个新的对象。
- Integer自动装箱细节分析
- Integer自动装箱的细节
- java自动装箱、拆箱——Integer细节
- 研究Integer的自动装箱
- Integer的自动装箱过程
- Integer自动装箱拆箱
- java自动装箱之Integer
- Integer对象自动装箱问题
- Integer自动装箱和Integer.valueOf()
- Integer自动拆箱、自动装箱
- Integer自动装箱、自动拆箱
- int Integer 装箱 拆箱 自动装箱 自动拆箱
- Integer的自动拆箱装箱陷阱
- Integer的自动装箱以及Int比较
- Integer的自动装箱与拆箱
- Java中Integer自动装箱误区
- Integer.valueOf(int)及自动装箱内幕
- Integer自动装箱超出赋值范围
- IAR编译优化
- 使用RTL-SDR和Matlab Simulink玩转软件无线电(二十)
- sql奇葩语句集合
- 【STL】poj 3781 Nth Largest Value
- CSS学习总结(1)
- Integer自动装箱细节分析
- myeclipse svn插件下载地址
- 实现1+2+3...+n,要求不能使用乘除法、循环、条件判断、选择相关的关键字
- 话说矩阵乘法...
- 课程学习周记 第二周
- 【LectCode】450. Delete Node in a BST
- fatfs 学习笔记--f_mkfs用法(最新版本R0.13)
- 企业级JAVA快速开发平台, 内置代码生成器
- usb1.1包的快速记忆口诀