【问题标题】:Regarding "+" operator and its StringBuilder implementation关于“+”运算符及其 StringBuilder 实现
【发布时间】:2017-02-14 19:43:29
【问题描述】:

据我了解,Java 中的字符串连接“+”运算符是使用 Stringbuilder 实现的,例如:

String s = "foo" + "bar" 

内部编译为:

String s = new StringBuilder().append("foo").append("bar").toString();

所以我尝试了这样的事情:

String foo1 = "foobar";
String foo2  = new String("foobar");
String foo3 = "foo" + "bar"; 
char[] fooarray = {'f','o','o','b','a','r'};
String foo4 = new String(fooarray);

接下来,我使用 == 运算符对它们进行了测试。结果大多符合我的预期:foo2 和 foo4 没有为任何其他字符串返回“==”。

但是,foo3 == foo1 返回 true。这是什么原因? StringBuilder 类的 toString 方法内部调用 "new String" ,所以 foo3 不应该是一个唯一的对象,就像 foo2 一样?

【问题讨论】:

  • 两个字符串literals的字符串连接由编译器完成,而不是在运行时。所以写"foo" + "bar" 和写"foobar" 是一样的。它允许您将字符串文字拆分为多行,而不会影响性能。
  • 另外,如果你的字符串是final,那么如果s1s2 是对字符串文字的引用,那么String s = s1 + s2 将在编译时发生

标签: java string stringbuilder string-concatenation


【解决方案1】:

foo3 == foo1 之所以返回 true 是因为 String pooling。

当您连接字符串字面量(甚至不是字面量的final 字符串)时,连接发生在编译时,因此当程序执行值String foo1 = "foobar";String foo3 = "foobar"; 时。

字符串池或字符串表是堆上存储字符串引用的特殊区域。

现在,当您创建字符串foo1 时,如果没有其他值为foobar 的字符串文字,它会保留在池中。但是在foo3 的情况下,已经有一个值为foobar 的字符串文字,所以foo1foo3 指向字符串池中的同一个对象,这样做是为了节省内存。

当您使用 new 关键字创建字符串时,对象驻留在堆上但在字符串池之外。

如果您希望使用 new 关键字创建的字符串在字符串池中,如果池中已经存在相同的值,那么您必须调用 String intern() 方法并将引用分配回 String 变量。

欲了解更多信息 - What is the Java string pool and how is “s” different from new String(“s”)?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-18
    • 2014-07-15
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 2013-03-17
    • 1970-01-01
    相关资源
    最近更新 更多