Intellij 警告 "StringBuffer.toString() in concatenation"

Intellij warning "StringBuffer.toString() in concatenation"

如果启用标题 "Performance issues" 下的所有检查,您将收到有关以下代码的警告(如标题所示):

StringBuilder sb = new StringBuilder("Two");
String s = "One" + sb.toString();

我意识到 toString() 是不必要的,但它在哪些方面是性能问题?

如果您要使用字符串连接运算符 (+),则使用 StringBuilder 毫无意义,它会在幕后创建一个 StringBuilder,从而导致创建两个 StringBuilder 对象而不是一个。您可以简单地重新使用 StringBuilder 来连接字符串:

StringBuilder sb = new StringBuilder("One");
sb.append("Two");
String s = sb.toString();

原代码等价于:

StringBuilder sb = new StringBuilder("Two");
StringBuilder sb2 = new StringBuilder("One");
String s = sb2.append(sb.toString()).toString();

与警告相关的另一个方面(老实说,与代码优化相比,它与性能的关系较小)是 toString() 在与 + 操作数一起使用时是多余的。这是因为编译器会自动调用toString()。这是您在问题中已经猜到的内容,并在 Java 语言规范中进行了解释:

(来自 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1):

If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.

其中 section 5.1.11 表示:

  • If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).

  • Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.

这里有 2 件事:

  1. "One" + "Two" 是最快的方法。在 运行 时间需要 0 纳秒(连接发生在编译时。)但 IntelliJ 不够智能,无法建立这种连接。

  2. 这可能是因为这是一件奇怪的事情,因为如果您在循环中执行 + 可以生成很多对象,而 StringBuilder 是避免该问题的一种方法。