从字节码层面分析==比较integer和int
作者:互联网
public class aaa {
public static void main(String[] args) {
Integer a = 1;
int b = 1;
System.out.println(a == b);
}
}
这样一段代码输出的是true,通过javap -c -l得到相应的字节码指令:
Code:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: iconst_1
6: istore_2
7: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
10: aload_1
11: invokevirtual #4 // Method java/lang/Integer.intValue:()I
14: iload_2
15: if_icmpne 22
18: iconst_1
19: goto 23
22: iconst_0
23: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
26: return
可以看出先把两个1存到操作栈中,然后把操作栈中的1存到局部变量表中,最后在比较的时候再把两个1从局部变量表中放到操作数栈中执行if_icmpne逻辑判断来进行比较。其中astore和istore是精髓,astore代表把integer自动拆箱用来存储到局部变量表中。
当数值改为127以上时,唯一改变的字节码指令是iconst->sipush,这是因为:
取值-128~127采用bipush指令,
取值-32768~32767采用sipush指令
取值-2147483648~2147483647采用 ldc 指令。
Code:
0: sipush 128
3: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
6: astore_1
7: sipush 128
10: istore_2
11: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
14: aload_1
15: invokevirtual #4 // Method java/lang/Integer.intValue:()I
18: iload_2
19: if_icmpne 26
22: iconst_1
23: goto 27
26: iconst_0
27: invokevirtual #5 // Method java/io/PrintStream.println:(Z)V
30: return
好了 下来看看int和int之间比较的字节码,把刚才的一个integer类型改为int:
Code:
0: bipush 127
2: istore_1
3: bipush 127
5: istore_2
6: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
9: iload_1
10: iload_2
11: if_icmpne 18
14: iconst_1
15: goto 19
18: iconst_0
19: invokevirtual #3 // Method java/io/PrintStream.println:(Z)V
22: return
可以看到只是astore->istore
最后我们再来看看两个integer之间的比较:
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
28: return
可以看到两个都变成了astore,结果也是true
再看看大于127:
Code:
0: sipush 128
3: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
6: astore_1
7: sipush 128
10: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
13: astore_2
14: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
17: aload_1
18: aload_2
19: if_acmpne 26
22: iconst_1
23: goto 27
26: iconst_0
27: invokevirtual #4 // Method java/io/PrintStream.println:(Z)V
30: return
虽然字节码相差不大,但是结果是false,是因为java虚拟机在启动时,会把-128-127之间的数字放到数字常量池中,所以在大于127时指向的地址是不相同的,比较为false。
有趣的是两个int相比较是永远true的,那是因为int在比较时,jvm会直接把两个int所对应的值放到常量池中,而integer不会。
标签:lang,Ljava,java,字节,int,iconst,Integer,integer,Method 来源: https://blog.csdn.net/weixin_48445640/article/details/120303334