浏览 2797 次
锁定老帖子 主题:自动装箱拆箱原理分析
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-03-06
JDK5.0之后为程序员提供了一种新特性:自动装箱拆箱,貌似是模仿C#的(到现在貌似有接近2年没有搞C#了,哥刚出来时还是搞C#滴)。 在JDK5.0之前 Integer val = 100; 如果这样写,是错误的(类型转换错误)。 虽然自动装箱拆箱用起来是很简单滴,但是明白它的原理,就能达到知其然,知其所以然的效果。 进入主题,分析自动装箱拆箱的背后原理。 public class Test { public static void main(String[] args) throws Exception { Integer one = 100; Integer two = 100; Integer three = 200; Integer four = 200; int five = 100; System.out.println(one == two); System.out.println(five == two); System.out.println(three == four); } } 结果是神马呢? 先不说结果,等分析就自然知道它的结果了。呵呵 先来看看它的字节码,看看它都做了些什么。 public static void main(java.lang.String[]) throws java.lang.Exception; Exceptions: throws java.lang.Exception Code: Stack=3, Locals=6, Args_size=1 0: bipush 100 // 将常数100压栈 2: invokestatic #19; //Method java/lang/Integer.valueOf:(I)Ljava/lang/I teger; // 调用Integer的valueOf方法 5: astore_1 // 将100赋给第一个变量 6: bipush 100 // 将常数100压栈 8: invokestatic #19; //Method java/lang/Integer.valueOf:(I)Ljava/lang/I teger; // 调用Integer的valueOf方法 11: astore_2 // 将100赋给第一个变量 12: sipush 200 15: invokestatic #19; //Method java/lang/Integer.valueOf:(I)Ljava/lang/I teger; 18: astore_3 19: sipush 200 22: invokestatic #19; //Method java/lang/Integer.valueOf:(I)Ljava/lang/I teger; 25: astore 4 27: bipush 100 29: istore 5 31: getstatic #25; //Field java/lang/System.out:Ljava/io/PrintStream; 34: aload_1 35: aload_2 36: if_acmpne 43 39: iconst_1 40: goto 44 43: iconst_0 44: invokevirtual #31; //Method java/io/PrintStream.println:(Z)V 47: getstatic #25; //Field java/lang/System.out:Ljava/io/PrintStream; 50: iload 5 52: aload_2 53: invokevirtual #37; //Method java/lang/Integer.intValue:()I // 调用Integer的intValue方法 56: if_icmpne 63 59: iconst_1 60: goto 64 63: iconst_0 64: invokevirtual #31; //Method java/io/PrintStream.println:(Z)V 67: getstatic #25; //Field java/lang/System.out:Ljava/io/PrintStream; 70: aload_3 71: aload 4 73: if_acmpne 80 76: iconst_1 77: goto 81 80: iconst_0 81: invokevirtual #31; //Method java/io/PrintStream.println:(Z)V 84: return 看了字节码后,有点恍然大悟的感觉。 1、装箱 原来执行下面语句时 Integer one = 100; 调用了Integer的静态方法valueOf(这可能是编译器处理的)。 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); } 此方法是JDK5.0之后才提供的,也就是所谓的“装箱”操作了。如果i的值在-128到127这个范围内,就会从“缓存”里面取它的值,如果超过这个范围的数,就直接返回i所代表的包装类。对-128到127这个范围内的数字进行缓存,可能是出于效率的考虑吧。 private static class IntegerCache { private IntegerCache(){} static final Integer cache[] = new Integer[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Integer(i - 128); } } 2、拆箱 System.out.println(five == two); 执行这句的时候,会把two转成原始int类型。调用Integer的实例方法intValue。 public int intValue() { return value; } 其中value是Integer的一个成员变量, private final int value; 简单吧,哈哈。。。。现在答案已经出来了。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |