Java 编译器( javac
) 将您的 Java代码转换为由JVM执行的字节码。它还为您做了一些优化。您可以使用带有参数的实用程序检查生成的字节码javap
-c
与最终字符串连接
c==a
是真的,因为这c
是final
此片段的字节码(仅最后比较):
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String Hello
2: astore_2
3: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
6: aload_2
7: ldc #2; //String Hello
9: if_acmpne 16
12: iconst_1
13: goto 17
16: iconst_0
17: invokevirtual #4; //Method java/io/PrintStream.println:(Z)V
20: return
}
如您所见,java 编译器已将“Hel”与“lo”合并,并仅比较两个字符串字母“Hello”。默认情况下,Java 实习生字符串文字 - 这就是它返回 true 的原因
与非最终字符串连接
如果您将字符串文字与非最终字符串变量连接起来,则字节码将有所不同:
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String lo
2: astore_1
3: ldc #3; //String Hello
5: astore_2
6: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_2
10: new #5; //class java/lang/StringBuilder
13: dup
14: invokespecial #6; //Method java/lang/StringBuilder."<init>":()V
17: ldc #7; //String Hel
19: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_1
23: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: if_acmpne 36
32: iconst_1
33: goto 37
36: iconst_0
37: invokevirtual #10; //Method java/io/PrintStream.println:(Z)V
40: return
}
在这里,我们正在比较java/lang/StringBuilder.toString:()Ljava/lang/String;
显然返回另一个对象的方法的结果 - 它的值等于“Hello”,而不是引用
您可以在此stackoverflow 问题中找到有关比较字符串的更多详细信息