String
将始终创建新的内存空间,而StringBuffer
则不会,只要我们附加新值,它就会更新现有的内存。
我的问题是:假设,我使用
new StringBuffer("A " + "B " + "C " + "D " + "E " + "F").toString();
如何完成内存分配?
答案 0 :(得分:1)
Java编译器足够聪明,可以在编译时连接String ABCDEF并将其加载为Compile time constant ..所以它只会在池中创建一个String。
答案 1 :(得分:1)
如果没有@Neerav描述的特殊情况优化(所以在较旧的JRE中,或者如果你没有文字字符串),你的代码最终会产生大量的CPU和内存开销。
你有"A " + "B " + "C " + "D " + "E " + "F"
这个词。这转化为(没有优化)
new StringBuilder("A ").append("B ").append("C ").append("D ")
.append("E ").append("F").toString()
执行代码行时,不会分配像"A "
这样的文字字符串。在加载类时,它们会预先分配到字符串池中。
您的代码会创建一个StringBuilder
(StringBuffer
的现代替代品)并将字符附加到其缓冲区。因此它分配StringBuilder
基础对象加上一个字符数组。也许初始缓冲区不够大,然后在某些时候StringBuilder
必须分配一个新的更大的数组,将字符从旧数组复制到新数组,然后继续。
最后,表达式必须是String
而不是StringBuilder
,因此您获得toString()
。这将创建一个新的String
基础对象以及一个具有完全正确大小的新字符数组。
然后将此表达式包装在new StringBuffer(...).toString()
中,这是完全不必要的。首先,这将创建一个新的StringBuffer
基础对象以及一个足够大的新字符数组,用于字符串并在那里复制字符。然后在此toString()
上调用StringBuffer
,这将创建另一个String
基本实例和字符数组,并再次将字符复制到此新String
对象中。您在String
之前已经完全相同new StringBuffer(...).toString()
。
所以,你分配: