给出以下代码:
StringBuffer str2 = new StringBuffer(" I don't");
StringBuffer str3 = str2.append(" get it.");
if (str2 == str3)
{
System.out.println("Equal");
}
我的讲师说,在这种情况下,str2
和str3
都会引用同一个对象
字符串“我不明白”将被插入“字符串池”。
我认为我明白为什么str2
和str3
现在将引用相同的对象,但为什么字符串“我不明白”。在str3
分配发生时进入字符串池?
例如,如果我这样做:
String s = "abcd";
然后我知道现在字符串“abcd”将被插入到“字符串池”中,如果它还没有存在。
我很想得到解释。
答案 0 :(得分:5)
为什么字符串“我不明白”。进入字符串池。
"I don't get it."
字符串无法进入实习池。
验证方法如下:
StringBuffer str2 = new StringBuffer(" I don't");
StringBuffer str3 = str2.append(" get it.");
String str = new String(str3.toString());
if (str == str.intern()) {
System.out.println("It was not interned before"); // <<== This is printed
} else {
System.out.println("It was interned before");
}
如果String
的内容被实习,则intern()
的调用将返回不同的(“规范”)对象。如您所见,上面返回相同的对象,这意味着您调用intern()
的对象刚刚成为“规范”对象(即已被实习)。
另一方面,如果您删除append
,则会得到不同的结果:
StringBuffer str2 = new StringBuffer(" I don't");
StringBuffer str3 = str2;
String str = new String(str3.toString());
if (str == str.intern()) {
System.out.println("It was not interned before"); // <<== This is printed
} else {
System.out.println("It was interned before");
}
现在str3
内的字符串为" I don't"
。它的副本已经被实现,因为它与创建str2
时使用的字符串常量相同。
您可以并排运行the first和the second程序,以便自己查看差异。
str2 == str3
为true
的原因与字符串池无关(俚语是"string interning")。这两者是相同的,因为StringBuffer.append
返回调用append
的对象,即str2
。你没有第二个对象 - 只有一个StringBuffer
有两个引用它。 StringBuffer
的内容是" I don't"
和" get it."
字符串的串联。
答案 1 :(得分:2)
你缺少的是string literal的概念。
在以下情况下添加到池中的字符串:
并且尚未进入池中。
在您的示例中,您将字符串文字放入StringBuffer
类型的对象中。要从该对象检索字符串,您必须调用toString()
。要将结果添加到字符串池,您必须另外在该字符串上调用intern()
。
证明我们可以进行简单的测试。
String s1 = "This is a simple test";
String s2 = "This is a simple test";
System.out.println(s1 == s2);
StringBuffer sb1 = new StringBuffer(s1);
StringBuffer sb2 = new StringBuffer(s2);
String result1 = sb1.toString();
String result2 = sb2.toString();
System.out.println(result1 == result2);
String internedResult1 = result1.intern();
String internedResult2 = result2.intern();
System.out.println(internedResult1 == internedResult2);
代码输出将是:
是的 假
真
答案 2 :(得分:0)
您要比较StringBuffer
个对象,而不是(实习)String
。如果您查看StringBuffer.append( String )
实施,则会注意到它以return this;
结尾,因此您的str2
和str3
是同一个对象。
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
编辑:当您的代码中的两个字符串文字被实习(在“字符串池”中)时,组合字符串“我不明白”将不会被实习。通过检查StringBuffer
代码(在内部将组合表示为char[]
数组,这一点很清楚。)
干杯,
答案 3 :(得分:0)
StringBuffer#append(StringBuffer sb)
将指定的StringBuffer追加到此序列。的人物 StringBuffer参数按顺序附加到。的内容 这个StringBuffer,增加了这个StringBuffer的长度 论证的长度。如果sb为null,则四个字符为“null” 附加到此StringBuffer。
设n是旧字符序列的长度,包含的字符序列 在执行append方法之前的StringBuffer中。然后 新字符序列中索引k处的字符等于 如果k小于,则旧字符序列中索引k处的字符 N;否则,它等于索引k-n中的字符 论证sb。
此方法在此(目标)对象上同步但不同步 同步源(sb)。
您将得到真实,因为两者的引用相同。
答案 4 :(得分:0)
似乎有些混乱。 StringBuffer是可变的,这意味着它的内容可以被修改。 StringBuffer中的方法append()将一个String附加到缓冲区内的字符串并返回实例。这一行:
StringBuffer str3 = str2.append(" get it.");
将具有与以下相同的实际结果:
str2.append(" get it.");
StringBuffer str3 = str2;
换句话说,str3和str2指向同一个对象。因为你附加了字符串文字“得到它”。为了“我不”,这个StringBuffer将包含“我不明白。”。
答案 5 :(得分:0)
为什么字符串“我不明白”。 str3分配发生时进入字符串池?
没有。你的讲师在这一点上是错误的。唯一可能发生的方法是StringBuffer调用String.intern(),但它没有,或者至少没有指定它。