这个陈述以其精确的形式是错误的,它符合链接博客继续写一些无稽之谈的情况,比如你必须用
Objects.toString(…)
包装引用来处理
null
,例如
"att1='" + Objects.toString(att1) + '\''
而不是只用
"att1='" + att1 + '\''
。没有必要这样做,显然,作者从未重新检查过这些声明。
JVM 不负责编译
+
运算符,因为这个运算符只是源代码工件。编译器,例如
javac
才是负责的,虽然编译后的形式没有保证,但编译器被鼓励使用构建器,由
Java 语言规范 确定。
一种实现可能选择在一步中执行转换和连接,以避免创建然后丢弃中间的String对象。为了增加重复字符串连接的性能,Java编译器可以使用StringBuffer类或类似的技术来减少通过表达式求值创建的中间String对象的数量。
请注意,即使编译器不执行此优化,字节码级别上仍不存在“+”运算符,因此编译器必须选择一个JVM理解的操作,例如使用String.concat,在只连接两个字符串的情况下,这可能比使用StringBuilder更快。
即使假设最坏的字符串连接编译策略(仍然在规范内),也不能说永远不要使用“+”连接字符串,因为当您定义编译时常量时,使用“+”是唯一的选择,当然,编译时常量通常比在运行时使用StringBuilder更有效率。
实际上,在 Java 5 之前,应用于非常量字符串的 + 操作符编译成了 StringBuffer 的使用方式,而在 Java 5 到 Java 8 中则编译成了 StringBuilder 的使用方式。当编译后的代码与手动使用 StringBuffer 或 StringBuilder 的代码相同时,其性能不会有差异。
超过十年以前切换到 Java 5 时,通过 + 进行字符串连接首次明显优于手动使用 StringBuffer,因为只需重新编译连接代码即可使其内部使用可能更快的 StringBuilder,而手动处理 StringBuffer 的代码则需要重写以使用在该版本中引入的 StringBuilder。
同样地,Java 9 将使用 invokedynamic 指令来编译字符串连接,允许 JRE 将其绑定到执行操作的实际代码,包括在普通 Java 代码中不可能进行的优化。因此,只需重新编译字符串连接代码即可获得此功能,而无法手动使用等效内容。
话虽如此,尽管字符串拼接从未被视为邪恶的前提是错误的,但建议是正确的,不要犹豫地使用它。
只有在需要大量初始容量或在循环内大量连接且该代码已被性能分析工具确认为实际性能瓶颈的情况下,您才真正可能通过手动处理缓冲区来提高性能...