String concat和Java中的+运算符有区别吗?

时间:2009-03-28 21:52:29

标签: java string

复制

  

java String concatenation

我很好奇两者之间的区别是什么。

我理解字符串池的方式是:

这会在字符串池中创建3个字符串对象,其中2个字符串对象将丢失。

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

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

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

我知道StringBuilder和StringBuffer在内存使用方面更有效率,因为需要进行大量的连接。我只是好奇,如果在内存使用方面+运算符和concat之间有任何区别。

4 个答案:

答案 0 :(得分:30)

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

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

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

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

相比之下,str1.concat(str2)只是创建了一个新的字符串,它是str1str2的串联,对于少量连接的字符串来说,它的成本较低(但会丢失到第一个字符串)接近一个更大的数字)。

此外,如果str1为空,请注意str1.concat(str2)会抛出NPE,但str1 += str2只会将str1视为空,而不会抛出异常。 (也就是说,它会产生“null”与str2的值连接。如果str2是,例如“foo”,那么你最终会得到“nullfoo”。)


更新:请参阅 this StackOverflow question ,这几乎完全相同。

答案 1 :(得分:7)

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

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

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

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

答案 2 :(得分:1)

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

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

还会创建3个字符串。

更多信息:http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html

答案 3 :(得分:1)

  

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

你似乎对这个词有误解。没有“字符串池”这样的东西 - 你使用它的方式,看起来你只是意味着堆上的所有String对象。 一个runtime constant pool,其中包含编译时字符串常量和从String.intern()返回的字符串实例