我很好奇两者之间的区别是什么。
我理解字符串池的方式是:
这会在字符串池中创建3个字符串对象,其中2个字符串对象将丢失。
String mystr = "str";
mystr += "end";
这不会在字符串池中创建3个对象吗?
String mystr = "str";
mystr = mystr.concat("end")
我知道StringBuilder和StringBuffer在内存使用方面更有效率,因为需要进行大量的连接。我只是好奇,如果在内存使用方面+运算符和concat之间有任何区别。
答案 0 :(得分:30)
这种特殊情况没有区别; 但是,它们通常不一样。
str1 += str2
相当于执行以下操作:
str1 = new StringBuilder().append(str1).append(str2).toString();
为了向自己证明这一点,只需创建一个简单的方法,它接受两个字符串,+=
是第一个字符串到第二个字符串,然后检查反汇编的字节码。
相比之下,str1.concat(str2)
只是创建了一个新的字符串,它是str1
和str2
的串联,对于少量连接的字符串来说,它的成本较低(但会丢失到第一个字符串)接近一个更大的数字)。
此外,如果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()
返回的字符串实例