java-int的封装类的比较

时间:2022-01-24 14:19:30

  1. /** 
  2.  *Q:Integer和Integer对象用  == 进行比较的过程是怎样的? 
  3.  * 
  4.  *看例子 
  5.  */  
  6. public class Test {  
  7.   
  8.     public static void main(String[] args) {  
  9.         int a = 1;  
  10.         int b = 1;  
  11.         Integer c = 3;  
  12.         Integer d = 3;  
  13.         Integer e = 321;  
  14.         Integer f = 321;  
  15.   
  16.         System.out.println(a == b);  
  17.         System.out.println(c == d);  
  18.         System.out.println(e == f);  
  19.   
  20.     }  
  21. }  
  22. output:  
  23. true  
  24. true  
  25. false  
  26.   
  27. 下面具体解释三个结果  
  28. 通过java命令   javap -c 得到下面的字节码  
  29.   
  30.  Compiled from "Test.java"  
  31. public class Test extends java.lang.Object{  
  32. public Test();  
  33.   Code:  
  34.    0:   aload_0  
  35.    1:   invokespecial   #1//Method java/lang/Object."<init>":()V  
  36.    4:   return  
  37.   
  38. public static void main(java.lang.String[]);  
  39.   Code:  
  40.    0:   iconst_1  //将int类型常量1压入栈   
  41.    1:   istore_1  //将int类型值存入局部变量1  
  42.    2:   iconst_1  //将int类型常量1压入栈  
  43.    3:   istore_2  //将int类型值存入局部变量2  
  44.    4:   iconst_3  //将int类型常量3压入栈  
  45.    5:   invokestatic    #2//Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; //调用Integer的静态方法 valueOf,构建整型值为3的Integer对象  
  46.    8:   astore_3  //将引用存入局部变量3  
  47.    9:   iconst_3  
  48.    10:  invokestatic    #2//Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;  
  49.    13:  astore  4  
  50.    15:  sipush  321  //将321压入栈  
  51.    18:  invokestatic    #2//Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;  
  52.    21:  astore  5  
  53.    23:  sipush  321  
  54.    26:  invokestatic    #2//Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;  
  55.    29:  astore  6  
  56.    31:  getstatic       #3//Field java/lang/System.out:Ljava/io/PrintStream;  
  57.    34:  iload_1   //从局部变量1中装载int类型值到栈  
  58.    35:  iload_2  
  59.    36:  if_icmpne       43  //从栈中pop出两个int类型值并进行大小比较  
  60.    39:  iconst_1  
  61.    40:  goto    44  
  62.    43:  iconst_0  
  63.    44:  invokevirtual   #4//Method java/io/PrintStream.println:(Z)V  
  64.    47:  getstatic       #3//Field java/lang/System.out:Ljava/io/PrintStream;  
  65.    50:  aload_3   //从局部变量3中装载引用到栈  
  66.    51:  aload   4  
  67.    53:  if_acmpne       60   //从栈中pop出两个引用值进行比较  
  68.    56:  iconst_1  
  69.    57:  goto    61  
  70.    60:  iconst_0  
  71.    61:  invokevirtual   #4//Method java/io/PrintStream.println:(Z)V  
  72.    64:  getstatic       #3//Field java/lang/System.out:Ljava/io/PrintStream;  
  73.    67:  aload   5  
  74.    69:  aload   6  
  75.    71:  if_acmpne       78  
  76.    74:  iconst_1  
  77.    75:  goto    79  
  78.    78:  iconst_0  
  79.    79:  invokevirtual   #4//Method java/io/PrintStream.println:(Z)V  
  80.    82:  return  
  81.   
  82. }  
  83.   
  84.   
  85. 整型值的比较很容易理解,就是值的大小比较  
  86.   
  87. 但是为什么下面的语句会是不同的结果:  
  88.   
  89.         System.out.println(c == d);  
  90.         System.out.println(e == f);  
  91.   
  92. 从字节码上看都是一样的指令,没有不同的地方  
  93. 原因就在Integer的方法 valueOf  
  94.   
  95. 我们来看这个方法的源码:字节码里调用的就是这个方法:   
  96.   
  97.  public static Integer valueOf(int i) {  
  98.         if(i >= -128 && i <= IntegerCache.high)  
  99.             return IntegerCache.cache[i + 128];  
  100.         else  
  101.             return new Integer(i);  
  102.     }  
  103.   
  104. private static class IntegerCache {  
  105.         static final int high;  
  106.         static final Integer cache[];  
  107.   
  108.         static {  
  109.             final int low = -128;  
  110.   
  111.             // high value may be configured by property  
  112.             int h = 127;  
  113.             if (integerCacheHighPropValue != null) {  
  114.                 // Use Long.decode here to avoid invoking methods that  
  115.                 // require Integer's autoboxing cache to be initialized  
  116.                 int i = Long.decode(integerCacheHighPropValue).intValue();  
  117.                 i = Math.max(i, 127);  
  118.                 // Maximum array size is Integer.MAX_VALUE  
  119.                 h = Math.min(i, Integer.MAX_VALUE - -low);  
  120.             }  
  121.             high = h;  
  122.   
  123.             cache = new Integer[(high - low) + 1];  
  124.             int j = low;  
  125.             for(int k = 0; k < cache.length; k++)  
  126.                 cache[k] = new Integer(j++);  
  127.         }  
  128.   
  129.         private IntegerCache() {}  
  130.     }  
  131.   
  132. Integer里弄了一个缓存,对于在 -128127 之间的数值,会直接使用该缓存里的对象  
  133.  也就是说 Integer c = 3 或者 Integer c = Integer.valueOf(3) ,最终 c 得到的是Integer里的缓存对象  
  134.  同理,d也是获得该相同对象因此 进行 c == d 比较时,c和d引用的是同一个对象,因此就true  
  135.  而对于321,已经超出缓存范围了,因此 valueOf 方法会生成一个新的Integer对象因此e和f就引用不同 的对象了,进行==比较,当然就false了  
  136.  另外,对Integer的缓存,我们在日常开发时,对于小的整型值应该充分利用Integer的缓存对象省去过多的对象创建,回收的操作,这样会极大的提高程序性能