7

给定以下代码:

StringBuffer str2 = new StringBuffer(" I don't");
    StringBuffer str3 = str2.append(" get it.");
    if (str2 == str3)
    {
        System.out.println("Equal");
    }

我的讲师说,在这种情况下,两者都str2str3引用同一个对象,并且字符串“我不明白”将被插入到“字符串池”中。

我想我明白了为什么str2str3现在将引用同一个对象,但是为什么字符串“我不明白”。str3分配发生时进入字符串池?

例如,如果我这样做:

 String s = "abcd";

然后我知道现在字符串“abcd”将被插入到“字符串池”中,如果它还没有的话。

我很想得到一个解释。

4

6 回答 6

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.

您可以并排运行第一个第二个程序,看看自己的区别。

str2 == str3is的原因true与字符串池无关(俚语是“字符串实习”)。两者相等,因为StringBuffer.append返回append调用 的对象,即str2。你没有第二个对象——只有一个对象有StringBuffer两个引用。其内容StringBuffer" I don't"" get it."字符串的连接。

于 2013-04-03T12:44:10.140 回答
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);

代码输出将是:

真假 真
_

于 2013-04-03T13:20:40.637 回答
0

您正在比较StringBuffer对象,而不是 (interned)String的。如果您查看StringBuffer.append( String )实现,您会注意到它以 结尾return this;,因此您的str2str3是同一个对象。

public synchronized StringBuffer append(String str) {
super.append(str);
    return this;
}

编辑:虽然您的代码中的两个字符串文字被实习(在“字符串池”中),但组合字符串“我不明白”不会被实习。通过检查StringBuffer代码(在内部将组合表示为char[]数组)可以清楚地看到这一点。

干杯,

于 2013-04-03T12:44:37.977 回答
0

StringBuffer#append(StringBuffer 某人)

将指定的 StringBuffer 附加到此序列。StringBuffer 参数的字符按顺序附加到此 StringBuffer 的内容,使此 StringBuffer 的长度增加参数的长度。如果 sb 为 null,则将四个字符“null”附加到此 StringBuffer。

设 n 为旧字符序列的长度,即在执行 append 方法之前包含在 StringBuffer 中的字符序列。那么如果k小于n,则新字符序列中索引k处的字符等于旧字符序列中索引k处的字符;否则,它等于参数 sb 中索引 kn 处的字符。

此方法在此(目标)对象上同步,但不在源 (sb) 上同步。

你会得到真实的,因为两者的参考是相同的。

于 2013-04-03T12:46:53.603 回答
0

似乎有些混乱。StringBuffer 是可变的,这意味着它的内容可以被修改。来自 StringBuffer的方法append()将 String 附加到缓冲区内的字符串并返回实例。所以这一行:

StringBuffer str3 = str2.append(" get it.");

将具有与以下相同的实际结果:

str2.append(" get it.");
StringBuffer str3 = str2;

换句话说,str3 和 str2 指向同一个对象。因为您附加了字符串文字“get it”。到“我不明白”,这个 StringBuffer 将包含“我不明白。”。

于 2013-04-03T12:49:16.993 回答
0

为什么字符串“我不明白”。当 str3 赋值发生时进入字符串池?

它没有。你的讲师在这一点上是错误的。可能发生的唯一方法是如果 StringBuffer 调用 String.intern(),它没有,或者至少没有指定这样做..

于 2013-04-03T12:52:57.630 回答