概述
今天同事遇到一个关于 Integer 的坑:有两个 Integer 对象,Integer i = 10000,Integer j = 10000,判断两个对象是否相等。Java里面基本类型都有对应的对象,并且回进行自动装箱和拆箱的操作,就误以为对象 i 和对象 j 是比较的整形值,但是结果确出乎意料。
参考代码
public class Test {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
System.out.println(a == b);
Integer i = 100001;
Integer j = 100001;
System.out.println(i == j);
}
}
运行结果为:
true
false
本以为输出结果应该是两个true,但是最终的答案出乎意料,于是查看编译以后Test类对应的字节码命令,字节码命令如下:
javap -v Test.class
得到的字节码命令如下:
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=5, args_size=1
0: bipush 100
2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: bipush 100
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
28: ldc #5 // int 100001
30: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
33: astore_3
34: ldc #5 // int 100001
36: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
39: astore 4
41: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
44: aload_3
45: aload 4
47: if_acmpne 54
50: iconst_1
51: goto 55
54: iconst_0
55: invokevirtual #4 // Method java/io/PrintStream.println:(Z)V
58: return
通过上面的字节码命令可以看出,Integer 的装箱是通过 invokestatic 指令,调用 Integer.valueOf() 方法实现的。对两个对象进行比较时,是通过 if_acmpne 指令比较两个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.low = -128, IntegerCache.high = 127,在Integer中将 -128 到 127 对应的 Integer 对象缓存到 IntegerCache中,如果给 Integer对象赋值 >= -128 或者 赋值 <= 127,就从缓存中获取,如果超出了 -128 - 127的范围,就在堆中创建一个 Integer 对象,感兴趣的同学可以用 HSDB 工具查看。
if_acmpne 指令会进行两个对象的比较,如果内存地址不一样就返回 false,这就解释了上面的情况,所以比较两个对象的时候还是调用equals方法靠谱
网友评论