专业编程基础技术教程

网站首页 > 基础教程 正文

Integer对象比较时的注意事项

ccvgpt 2024-08-06 12:35:44 基础教程 34 ℃

1,关于Integer对象的比较,主要是注意如下知识点(xxx表示某个整数值);

Integer a1 = xxx;与Integer a1 = Integer.valueOf(xxx);是完全相同的赋值方式的,只是前者是自动装箱,后者是手动编码装箱,以下可以说明:

Integer对象比较时的注意事项

对于如下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

最近发表
标签列表