Sum*_*rma 18 java string string-interning
public static void main(String[] args) {
String a = new String("lo").intern();
final String d = a.intern();
String b = "lo";
final String e = "lo";
String c = "Hello";
System.out.println(b==a);//true
System.out.println(d==a);//true
System.out.println(e==a);//true
System.out.println(c=="Hel"+a); //why is this false? when e==a is true
System.out.println(c=="Hel"+d); //why is this false?
System.out.println(c=="Hel"+b); //why is this false?
System.out.println(c=="Hel"+e); //this is true
}
Run Code Online (Sandbox Code Playgroud)
这导致了
true
true
true
false
false
false
true
Run Code Online (Sandbox Code Playgroud)
表达式e==a为true意味着相同的引用.那么为什么最后一个表达式是真的但是第四个到最后一个表示c== "Hel"+a是假的?
Boh*_*ian 16
表达方式
"Hel" + a
Run Code Online (Sandbox Code Playgroud)
不是编译时间常量.实际上,它编译为:
new StringBuilder().append("Hel").append(a).toString()
Run Code Online (Sandbox Code Playgroud)
(或类似的)在运行时创建一个新的String对象.
然而,因为e是最后时,编译器可以确定的串联"Hel"和e的值是恒定值,所以它实习生.
Iły*_*sov 10
所有这些字符串都是在运行时计算的,这就是它们不同的原因
System.out.println(c=="Hel"+a); //why is this false? when e==a is true
System.out.println(c=="Hel"+d); //why is this false?
System.out.println(c=="Hel"+b); //why is this false?
Run Code Online (Sandbox Code Playgroud)
这个在编译期间计算,因为e是最终的:
System.out.println(c=="Hel"+e); //this is true
Run Code Online (Sandbox Code Playgroud)
如果您将代码更改为:
System.out.println(c==("Hel"+a).intern()); //why is this false? when e==a is true
System.out.println(c==("Hel"+d).intern()); //why is this false?
System.out.println(c==("Hel"+b).intern()); //why is this false?
Run Code Online (Sandbox Code Playgroud)
所有这些都会产生真实的
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
}
Run Code Online (Sandbox Code Playgroud)
如您所见,java编译器已将"Hel"与"lo"合并,只比较两个字符串leterals"Hello".Java默认情况下实习字符串文字 - 这就是它返回true的原因
与非final String连接
如果将字符串文字与非final String变量连接起来,则字节代码将不同:
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
}
Run Code Online (Sandbox Code Playgroud)
这里我们比较java/lang/StringBuilder.toString:()Ljava/lang/String;显然返回另一个对象的方法的结果- 它等于"Hello"值而不是引用
您可以在此stackoverflow问题中找到有关比较字符串的更多详细信息
| 归档时间: |
|
| 查看次数: |
659 次 |
| 最近记录: |