autoBoxing

转载自:

http://blog.csdn.net/ma451152002/article/details/9076793

http://blog.csdn.net/snail_rao/article/details/7639194

jdk的不可变类:

primitive变量: boolean,byte, char, double ,float, integer, long, short
jdk的不可变类:jdk的java.lang包中 Boolean, Byte, Character, Double, Float, Integer, Long, Short, String.


其实Integer与int类型的赋值与比较最关键的一点就是:这两个变量的类型不同。Integer是引用类型,int是原生数据类型。
        我们分四种情况来讨论:
        1) Integer与int类型的赋值
                a.把Integer类型赋值给int类型。此时,int类型变量的值会自动装箱成Integer类型,然后赋给Integer类型的引用,这里底层就是通过调用valueOf()这个方法来实现所谓的装箱的。
                b.把int类型赋值给Integer类型。此时,Integer类型变量的值会自动拆箱成int类型,然后赋给int类型的变量,这里底层则是通过调用intValue()方法来实现所谓的拆箱的。
        2) Integer与int类型的比较
                这里就无所谓是谁与谁比较了,Integer == int与int == Integer的效果是一样的,都会把Integer类型变量拆箱成int类型,然后进行比较,相等则返回true,否则返回false。同样,拆箱调用的还是intValue()方法。
        3) Integer之间的比较
                这个就相对简单了,直接把两个引用的值(即是存储目标数据的那个地址)进行比较就行了,不用再拆箱、装箱什么的。
        4) int之间的比较
                这个也一样,直接把两个变量的值进行比较。
        值得注意的是:对Integer对象,JVM会自动缓存-128~127范围内的值,所以所有在这个范围内的值相等的Integer对象都会共用一块内存,而不会开辟多个;超出这个范围内的值对应的Integer对象有多少个就开辟多少个内存。底层代码如下:

  1.  public static Integer valueOf(int i) {  
  2.         assert IntegerCache.high >= 127;  
  3.         if (i >= IntegerCache.low && i <= IntegerCache.high)  
  4.             return IntegerCache.cache[i + (-IntegerCache.low)];  
  5.         return new Integer(i);  
  6.     } 

测试代码如下:

  1. public class IntegerAndIntTest  
  2. {  
  3.     public static void main(String[] args) throws Exception  
  4.     {  
  5.         Integer a = 127, b = 128;  
  6.           
  7.         int c = 128;  
  8.           
  9.         //自动装箱,这里会调用Integer中的valueOf方法把c装箱成Integer类型  
  10.         a = c;  
  11.           
  12.         //这里比较的是两个对象的地址,显然不等  
  13.         System.out.println(a == b);  
  14.           
  15.         //这里会调用Integer的intValue方法获得Integer对象a指向的栈地址中存的值再与c进行值比较,  
  16.         //而不是把c装箱成Integer类型进行地址比较  
  17.         System.out.println(a == c);  
  18.           
  19.         //同上,也是获得a指向的栈地址中存的值  
  20.         System.out.println(c == a);  
  21.           
  22.         /** 
  23.          * 总结:只有在赋值(=)的时候才会出现装箱和拆箱两种情况, 
  24.          * 在比较(==)的时候只会出现一种情况,那就是拆箱,而不会出现装箱的情况 
  25.          */  
  26.         System.out.println("----------------------------------");  
  27.           
  28.         Integer i1 = 127;  
  29.         Integer i2 = 127;  
  30.           
  31.         System.err.println(i1 == i2);  
  32.         i1 = 128;  
  33.         i2 = 128;  
  34.         System.err.println(i1 == i2);  
  35.           
  36.         /** 
  37.          * 总结:JVM会自动缓存-128~127范围内的值,所以所有在这个范围内的值相等的Integer对象都会共用一块内存,而不会开辟多个; 
  38.          * 超出这个范围内的值对应的Integer对象有多少个就开辟多少个内存,这样做是为了节省内存消耗。 
  39.          */  
  40.     }  

  反编译结果:具体看第2、9、22、27、38、72、92、116、123、149、157等行,这几行涉及到装箱、拆箱。

  1. public static void main(java.lang.String[]) throws java.lang.Exception;  
  2.     flags: ACC_PUBLIC, ACC_STATIC  
  3.     Exceptions:  
  4.       throws java.lang.Exception  
  5.     Code:  
  6.       stack=3, locals=7, args_size=1  
  7.          0: bipush        127  
  8.          2: invokestatic  #19                 // Method java/lang/Integer.valueO  
  9. f:(I)Ljava/lang/Integer;  
  10.          5: astore_1  
  11.          6: sipush        128  
  12.          9: invokestatic  #19                 // Method java/lang/Integer.valueO  
  13. f:(I)Ljava/lang/Integer;  
  14.         12: astore_2  
  15.         13: sipush        128  
  16.         16: istore_3  
  17.         17: bipush        127  
  18.         19: istore        4  
  19.         21: iload_3  
  20.         22: invokestatic  #19                 // Method java/lang/Integer.valueO  
  21. f:(I)Ljava/lang/Integer;  
  22.         25: astore_1  
  23.         26: aload_1  
  24.         27: invokevirtual #25                 // Method java/lang/Integer.intVal  
  25. ue:()I  
  26.         30: istore        4  
  27.         32: getstatic     #29                 // Field java/lang/System.out:Ljav  
  28. a/io/PrintStream;  
  29.         35: iload         4  
  30.         37: aload_1  
  31.         38: invokevirtual #25                 // Method java/lang/Integer.intVal  
  32. ue:()I  
  33.         41: if_icmpne     48  
  34.         44: iconst_1  
  35.         45: goto          49  
  36.         48: iconst_0  
  37.         49: invokevirtual #35                 // Method java/io/PrintStream.prin  
  38. tln:(Z)V  
  39.         52: getstatic     #29                 // Field java/lang/System.out:Ljav  
  40. a/io/PrintStream;  
  41.         55: aload_1  
  42.         56: aload_2  
  43.         57: if_acmpne     64  
  44.         60: iconst_1  
  45.         61: goto          65  
  46.         64: iconst_0  
  47.         65: invokevirtual #35                 // Method java/io/PrintStream.prin  
  48. tln:(Z)V  
  49.         68: getstatic     #29                 // Field java/lang/System.out:Ljav  
  50. a/io/PrintStream;  
  51.         71: aload_1  
  52.         72: invokevirtual #25                 // Method java/lang/Integer.intVal  
  53. ue:()I  
  54.         75: iload_3  
  55.         76: if_icmpne     83  
  56.         79: iconst_1  
  57.         80: goto          84  
  58.         83: iconst_0  
  59.         84: invokevirtual #35                 // Method java/io/PrintStream.prin  
  60. tln:(Z)V  
  61.         87: getstatic     #29                 // Field java/lang/System.out:Ljav  
  62. a/io/PrintStream;  
  63.         90: iload_3  
  64.         91: aload_1  
  65.         92: invokevirtual #25                 // Method java/lang/Integer.intVal  
  66. ue:()I  
  67.         95: if_icmpne     102  
  68.         98: iconst_1  
  69.         99: goto          103  
  70.        102: iconst_0  
  71.        103: invokevirtual #35                 // Method java/io/PrintStream.prin  
  72. tln:(Z)V  
  73.        106: getstatic     #29                 // Field java/lang/System.out:Ljav  
  74. a/io/PrintStream;  
  75.        109: ldc           #41                 // String ------------------------  
  76. ----------  
  77.        111: invokevirtual #43                 // Method java/io/PrintStream.prin  
  78. tln:(Ljava/lang/String;)V  
  79.        114: bipush        127  
  80.        116: invokestatic  #19                 // Method java/lang/Integer.valueO  
  81. f:(I)Ljava/lang/Integer;  
  82.        119: astore        5  
  83.        121: bipush        127  
  84.        123: invokestatic  #19                 // Method java/lang/Integer.valueO  
  85. f:(I)Ljava/lang/Integer;  
  86.        126: astore        6  
  87.        128: getstatic     #46                 // Field java/lang/System.err:Ljav  
  88. a/io/PrintStream;  
  89.        131: aload         5  
  90.        133: aload         6  
  91.        135: if_acmpne     142  
  92.        138: iconst_1  
  93.        139: goto          143  
  94.        142: iconst_0  
  95.        143: invokevirtual #35                 // Method java/io/PrintStream.prin  
  96. tln:(Z)V  
  97.        146: sipush        128  
  98.        149: invokestatic  #19                 // Method java/lang/Integer.valueO  
  99. f:(I)Ljava/lang/Integer;  
  100.        152: astore        5  
  101.        154: sipush        128  
  102.        157: invokestatic  #19                 // Method java/lang/Integer.valueO  
  103. f:(I)Ljava/lang/Integer;  
  104.        160: astore        6  
  105.        162: getstatic     #46                 // Field java/lang/System.err:Ljav  
  106. a/io/PrintStream;  
  107.        165: aload         5  
  108.        167: aload         6  
  109.        169: if_acmpne     176  
  110.        172: iconst_1  
  111.        173: goto          177  
  112.        176: iconst_0  
  113.        177: invokevirtual #35                 // Method java/io/PrintStream.prin  
  114. tln:(Z)V  
  115.        180: return 

Integer的自动拆装箱的陷阱(整型数-128到127的值比较问题):

1、先看下面的例子:

  1. package integerdemo;  
  2.    
  3. public class IntegerDemo {  
  4.     
  5.     public static void main(String[] args) {  
  6.        //-128--127之间  
  7.         Integer i1 = 100;  
  8.         Integer i2 = 100;  
  9.           
  10.         if( i1 == i2){  
  11.             System.out.println("i1 == i2");  
  12.         }else{  
  13.             System.out.println("i1 != i2 ");  
  14.         }  
  15.           
  16.        //大于127    
  17.         Integer i3 = 200;  
  18.         Integer i4 = 200;  
  19.           
  20.         if( i3 == i4){  
  21.             System.out.println("i3 == i4");  
  22.         }else{  
  23.             System.out.println("i3 != i4 ");  
  24.         }  
  25.           
  26.     }  
  27. }  

运行结果:

  1. run:  
  2. i1 == i2  
  3. i3 != i4   
  4. 成功构建 (总时间: 1 秒)  


以上是靠整型数的自动拆装箱实现的,而两者的结果却不相同。

原因在于,在进行自动拆装箱时,编译器会使用Integer.valueof()来创建Integer实例。

2、以下是Integer.valueof()的源代码:

  1. public static Integer valueOf(int i) {  
  2.       assert IntegerCache.high >= 127;  
  3.       if (i >= IntegerCache.low && i <= IntegerCache.high)  
  4.           return IntegerCache.cache[i + (-IntegerCache.low)];  
  5.       return new Integer(i);  
  6.   }  

简单地解释这段代码,就是如果传入的int在IntegerCache.low和IntegerCache.high之间,那就尝试看前面的缓存中有没有打过包的相同的值,如果有就直接返回,否则就创建一个Integer实例。IntegerCache.low 默认是-128;IntegerCache.high默认是127.

注:如果要比较两个对象的内容是否相同,尽量不使用== 或者!= 来比较,可以使用equal()来实现。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值