为什么调试String拼接时会弹出StringBuilders?
因为字符串连接(通过“+”运算符)通常编译为使用 aStringBuffer
或StringBuilder
进行连接的代码。JLS 明确允许这种行为。
“实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间字符串对象。为了提高重复字符串连接的性能,Java 编译器可以使用 StringBuffer 类或类似技术来减少通过评估表达式创建的中间字符串对象。” JLS 15.18.1。
(如果您的代码使用 aStringBuffer
而不是 a StringBuilder
,可能是因为它是使用非常旧的 Java 编译器编译的,或者因为您指定了非常旧的目标 JVM。StringBuilder
该类是对 Java 的相对补充。旧版本的 JLS用来StringBuffer
代替StringBuilder
,IIRC。)
此外,也许您可以指出哪些是 JVM 特定的,哪些不是。
生成的字节码"string" + variable"
取决于 Java 编译器如何处理连接。(事实上,所有生成的字节码在某种程度上都依赖于 Java 编译器。JLS 和 JVM 规范没有规定必须生成哪些字节码。规范更多的是关于程序应该如何表现,以及单个字节码的作用。)
@supercat 评论:
我想知道为什么字符串连接不会使用例如接受两个字符串对象、分配适当组合大小的缓冲区并将它们连接起来的字符串构造函数重载?或者,当连接更多字符串时,需要一个 String[] 的重载?创建一个包含对要连接的字符串的引用的 String[] 应该不会比创建一个 StringBuilder 更昂贵,并且能够一次性创建一个完美大小的后备存储应该是一个简单的性能胜利。
也许......但我会说可能不是。这是一个涉及复杂权衡的复杂领域。为字符串连接选择的实施策略必须在各种不同的用例中都能很好地工作。
我的理解是,最初的策略是在查看了许多方法之后选择的,并进行了一些大规模的静态代码分析和基准测试,以试图找出哪种方法最好。我想他们考虑了您提出的所有替代方案。(毕竟,他们是/是聪明人......)
话虽如此,Java 6、7 和 8 的完整源代码库可供您使用。这意味着您可以下载它,并尝试自己的一些实验,看看您的理论是否正确。如果它们是……并且您可以收集确凿的证据证明它们是……然后向 OpenJDK 团队提交补丁。