Java中的String concat和+运算符之间有区别吗? [复制]

Posted

技术标签:

【中文标题】Java中的String concat和+运算符之间有区别吗? [复制]【英文标题】:Is there a difference between String concat and the + operator in Java? [duplicate] 【发布时间】:2010-10-16 04:02:33 【问题描述】:

复制

java String concatenation

我很好奇这两者有什么区别。

我对字符串池的理解是这样的:

这会在字符串池中创建 3 个字符串对象,其中 2 个所有引用都丢失了。

String mystr = "str";
mystr += "end";

这不也是在字符串池中创建3个对象吗?

String mystr = "str";
mystr = mystr.concat("end")

我知道当需要进行大量连接时,StringBuilder 和 StringBuffer 在内存使用方面的效率要高得多。我只是好奇 + 运算符和 concat 在内存使用方面是否有任何区别。

【问题讨论】:

我认为这里只实习了 2 个字符串; “str”和“end”。字符串 'strend' 没有被保留,因为它不是文字;你必须手动实习。有人可以确认/否认吗? 在完全相同的副本中查看我的答案:***.com/questions/47605/java-string-concatenation @Outlaw 在生成的代码中我看到没有调用实习生,但我没有查看 concat 的源代码,我不知道是否允许 VM 实习或编译器是否允许必须。 【参考方案1】:

除非 concat 的参数是空字符串,否则

String mystr = "str";
mystr = mystr.concat("end")

还将创建 3 个字符串。

更多信息:https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html

【讨论】:

其中两个是通过加载代码创建的,而不是通过执行它。 += 使用 StringBuilder。【参考方案2】:

在这种特殊情况下没有区别; 但是,它们通常不一样。

str1 += str2 相当于执行以下操作:

str1 = new StringBuilder().append(str1).append(str2).toString();

为了向自己证明这一点,只需创建一个简单的方法,它接受两个字符串,+= 的第一个字符串到第二个字符串,然后检查反汇编的字节码。

相比之下,str1.concat(str2) 只是创建一个新字符串,它是str1str2 的串联,对于少量串联的字符串来说成本更低(但会输给更大数量的第一种方法) .

此外,如果str1 为空,请注意str1.concat(str2) 会引发NPE,但str1 += str2 将简单地将str1 视为空,而不会引发异常。 (也就是说,它产生与 str2 的值连接的“null”。如果 str2 是,比如说,“foo”,你会得到“nullfoo”。)


更新:参见this *** question,几乎完全相同。

【讨论】:

concat 比较便宜。为了证明,请阅读 JLS,而不是 hack 绘制谬误。 @Tom:感谢您的反馈。 concat() 仅对于少量字符串来说更便宜。 StringBuilder 以更大的 N 获胜。我澄清了我的答案以使这一点更清楚。 你最后一个例子不正确,加法会导致“nullstr2”(如果str2的值当然是“str2”)concat确实会导致NPE。 @Jorn:呃。我的意思是说“str1 将被视为 null”。不知道我的手指是如何输入实际内容的。谢谢你的收获。【参考方案3】:

我对字符串池的理解 这是:

您似乎对该术语有误解。没有“字符串池”之类的东西 - 你使用它的方式,看起来你只是指堆上的所有 String 对象。 一个runtime constant pool,其中包含许多其他内容,包括编译时字符串常量和从String.intern()返回的字符串实例

【讨论】:

【参考方案4】:

+=concat() 之间的重要区别不是性能,而是语义。 concat() 将只接受字符串参数,但+(或+=)将接受任何东西。如果非字符串操作数是对象,则通过调用toString()将其转换为字符串;原语将被转换,就好像通过调用相关包装类中的适当方法一样,例如,Integer.toString(theInt);并且一个空引用变成了字符串"null"

实际上,我不知道为什么concat() 甚至存在。人们在 API 文档中看到它并认为它存在是有充分理由的——性能是最明显的原因。但这是一条红鲱鱼;如果性能确实是一个问题,您应该使用 StringBuilder,正如 John 链接到的线程中所讨论的那样。否则,++= 会更方便。

编辑:关于“在字符串池中创建对象”的问题,我认为您误解了字符串池是什么。在运行时,实际的字符序列,“str”和“end”将存储在一个专用的数据结构中,无论你在源代码中看到文字"str""end",字节码都会真正包含引用到该数据结构中的相应条目。

事实上,字符串池是在加载类时填充的,而不是在运行包含字符串文字的代码时填充的。这意味着您的每个 sn-ps 只创建一个对象:连接的结果。 (还有一些在幕后创建对象,每种技术都有点不同,但性能影响不值得担心。)

【讨论】:

以上是关于Java中的String concat和+运算符之间有区别吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

JAVA中的“+”“concat”和“append”

前端学数据库之函数

[ Java学习基础 ] String字符串的基本操作

java string

Java String类

JavaScript 中 + 运算符和 concat() 方法有啥区别