1,关于Integer对象的比较,主要是注意如下知识点(xxx表示某个整数值);
Integer a1 = xxx;与Integer a1 = Integer.valueOf(xxx);是完全相同的赋值方式的,只是前者是自动装箱,后者是手动编码装箱,以下可以说明:
对于如下code
public static void main(String[] args) { Integer a1 = 127; Integer b1 = 127; // 第1处,true System.out.println(a1 == b1); }
通过反编译其对应的class文件,得到的如下汇编指令中我们可以看到 Integer a1 = 127; 赋值操作实际上是通过调用Integer.valueOf(int i))方法来完成自动装箱的
public static void main(java.lang.String[]); Code: 0: bipush 127 2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: astore_1 6: bipush 127 8: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 11: astore_2 12: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 15: aload_1 16: aload_2 17: if_acmpne 24 20: iconst_1 21: goto 25 24: iconst_0 25: invokevirtual #4 // Method java/io/PrintStream.println:(Z)V
对于Integer.valueOf(xxx); 如果xxx>= -127且xxx<=127时,会默认取本地缓存中的数据,否则就创建一个Integer对象
首先我们看下Integer.valueOf()方法的实现源码:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
而其中用到的静态类IntegerCache源码如下:
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) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
通过IntegerCache静态类可以看出,在加载该类时会首先执行static { } 静态代码块。默认进行始化一个cache数组,并分别以[-128, 127]范围内的整数作为值创建Integer对象,分别赋值到cache数组,作为本地缓存。
回到Integer.valueOf()方法:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
我们可以看到,
1) 如果调用该方法传入的数据值在-127和IntegerCache.high(默认为127)之间,则返回对应的缓存中的包装类对象
其中获取缓存中对象时的数组下标i + (-IntegerCache.low),是因为缓存数组下标是从0起的,下标为0时对应的是-128。所以获取-128的包装类时,对应的下标就应该为-128 + (-IntegerCache.low) = 0
2) 如果调用该方法传入的数值不在[-128, 127] 范围内时,则创建一个新的Integer对象
备注:缓存区间[-128, 127] 是可以更改的,但是区间下限-128不能更改,只能变更区间上限,且上限必须大于或等于127,可以通过-XX:AutoBoxCacheMax=<size>来配置
2,示例代码:
public class Main { public static void main(String[] args) { Integer a1 = 127; Integer b1 = 127; // 第1处,true System.out.println(a1 == b1); Integer a2 = 128; Integer b2 = 128; // 第2处,false System.out.println(a2 == b2); Integer a3 = Integer.valueOf(127); Integer b3 = Integer.valueOf(127); // 第3处,true System.out.println(a3 == b3); Integer a4 = Integer.valueOf(128); Integer b4 = Integer.valueOf(128); // 第4处,false System.out.println(a4 == b4); Integer a5 = 127; Integer b5 = Integer.valueOf(127); // 第5处,true System.out.println(a5 == b5); Integer a6 = 127; Integer b6 = new Integer(127); // 第6处,false System.out.println(a6 == b6); Integer a7 = new Integer(1); Integer b7 = new Integer(1); // 第7处,false System.out.println(a7 == b7); } }
第1、3、5处,实际上每一个引用都是获取到的缓存中的包装类对象的地址,所以输出结果为true,
第2、4、7处,每一个引用都是指向新生成的不同的Integer对象地址,所以输出结果为fase,
第6处,a6指向的是缓存中的Integer对象地址,而b6指向新生成的Integer对象地址,所以结果为false