在 Java 中,String concat 和 + 运算符之间有区别吗?

2022-09-02 09:09:37

重复

java String concatenation

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

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

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

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

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

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

我知道StringBuilder和StringBuffer在内存使用方面效率要高得多,因为有很多连接需要完成。我只是好奇+运算符和concat在内存使用方面是否有任何区别。


答案 1

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

str1 += str2等效于执行以下操作:

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

为了证明这一点,只需制作一个简单的方法,将两个字符串和第一个字符串转换为第二个字符串,然后检查反汇编的字节码。+=

相比之下,只需创建一个新字符串,即 和 的串联,这对于少量串联字符串来说成本较低(但会输给具有较大数字的第一种方法)。str1.concat(str2)str1str2

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


更新:请参阅此 StackOverflow 问题,它几乎完全相同。


答案 2

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

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

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

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