从JVM指令看String对象的比较

在翻看各类 java 知识中,总会提到如下知识:比较 String 对象,例如:

String a1=new String("10");
String a2="10";
String a3="1"+"0";

//结果
System.out.println(a1==a2); //false
System.out.println(a2==a3); //true

在刚学习 java 知识的时候,对于这个结果感到非常意外且不理解,还曾一度尝试去死记硬背。虽然网上的文章也有对此分析居多,但是在接触 JVM 后,发现原因其实非常简单。

在将代码编译成的字节码后,便能看出来:

 0 new #7 <java/lang/String>   //创建一个String对象,并将其引用值压入栈顶
 3 dup  //复制栈顶值(即String对象的引用)
 4 ldc #9 <10>  //将String常量值"10"从常量池推送到栈顶
 6 invokespecial #11 <java/lang/String.<init> : (Ljava/lang/String;)V>  //调用java.lang.String#String(java.lang.String)构造方法
 9 astore_1  //将栈顶引用型数值(即String对象的引用)存入第一个本地变量
10 ldc #9 <10>  //将String常量值"10"从常量池推送到栈顶
12 astore_2  //将栈顶引用型数值(即常量值"10")存入第二个本地变量
13 ldc #9 <10>  //将String常量值"10"从常量池推送到栈顶
15 astore_3  //将栈顶引用型数值(即常量值"10")存入第三个本地变量

查看常量池,可知 #9 指向了 constant_String_info String 常量池,存储值为 10。

从字节码可知,变量 a1 是基于 String 常量值创建的 String 对象,而 a2a3 则是指向同一个 String 常量的引用。因此使用 = 比较的话,a1a2a3 并不相等,而 a2a3 相等。

顺便说一句,也有一个同样关于 String 对象的问题,就是说下面代码创建了多少个 String 对象:

String a1=new String("10");
String a2=new String("10");

如果常量池中不存在 String 常量值 “10”,jvm 会先创建一个 String 对象,再放到常量池中。然后再基于常量池中的 String 常量 “10”,分别创建 a1a2 对象,由此可知,上面代码创建了 3 个对象。

你可能感兴趣的:(JVM,jvm,java)