代码如下:
String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);
String s3 = new String("1")+new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
Run Code Online (Sandbox Code Playgroud)
上面代码的输出是:
false
true
Run Code Online (Sandbox Code Playgroud)
我知道s并且s2是不同的对象,因此结果的计算结果为false,但第二个结果的计算结果为true.有人能告诉我区别吗?
Rob*_*sen 23
这是发生了什么:
String s1 = new String("1");
s1.intern();
String s2 = "1";
Run Code Online (Sandbox Code Playgroud)
"1"(传递给String构造函数)在地址A处实现.s1在地址B处创建,因为它不是文字或常量表达式.intern()无效.字符串"1"已经实现,并且操作的结果未分配回s1.s2与值"1"从字符串池检索,所以点,以解决一个.结果:字符串s1并s2指向不同的地址.
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
Run Code Online (Sandbox Code Playgroud)
s3在地址C处创建.intern()将带有"11"地址C值的字符串添加到字符串池.s4与值"11"从字符串池检索,所以指向地址Ç.结果:字符串s3并s4指向相同的地址.
字符串"1"在调用之前intern()被实现,因为它存在于s1 = new String("1")构造函数调用中.
更改构造函数调用s1 = new String(new char[]{'1'})将使s1 == s2evaluate 的比较为true,因为两者现在将引用通过调用显式实现的字符串s1.intern().
(我使用了这个答案中的代码来获取有关字符串内存位置的信息.)
che*_*ohi 12
对于场景1:
String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);
Run Code Online (Sandbox Code Playgroud)
使用字节码:
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String 1
6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
10: aload_1
11: invokevirtual #5 // Method java/lang/String.intern:()Ljava/lang/String;
14: pop
15: ldc #3 // String 1
Run Code Online (Sandbox Code Playgroud)
因为String s = new String("1");它会创建一个新String对象,它将有一个新的地址"1",它已经在String Pool中:
ldc #3 // String 1
并且s2,作为字节码:
15: ldc #3 // String 1
s2指向String Pool变量:"1",所以s并且s2具有不同的地址和结果false.
对于场景2:
String s3 = new String("1")+new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
Run Code Online (Sandbox Code Playgroud)
使用字节码:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: aload_1
9: ldc #4 // String 1
11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #4 // String 1
16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_2
23: aload_2
24: invokevirtual #7 // Method java/lang/String.intern:()Ljava/lang/String;
27: astore_3
28: ldc #8 // String 11
Run Code Online (Sandbox Code Playgroud)
作为字节码,您可以看到new String("1")+new String("1");通过使用创建StringBuilder
new #2 // class java/lang/StringBuilder
它完全是一个没有String Pool变量的新Object .
之后s3.intern(),该方法将增加电流s3的存储器串池和8: aload_1.
并s4试图从中加载
ldc #8 // String 11
所以s3和s4地址应该相等,结果是真的.