Why is this an issue?

The use of a StringBuilder or StringBuffer makes String assembly more efficient than plain concatenation when you perform a large number of appends. Using String concatenation within StringBuilder.append defeats the purpose of the StringBuilder. If you concatenate only a few strings, use direct String concatenation. Otherwise, replace String concatenation with calls to append.

This rule applies to String concatenations performed repeatedly, inside loops. In such scenarios, the performance penalty associated with inefficient StringBuilder.append usage can multiply significantly.

Noncompliant code example

StringBuilder sb = new StringBuilder();
for (String name : names) {
  sb.append("Hello : " + name); // Noncompliant
}

Compliant solution

StringBuilder sb = new StringBuilder();
for (String name : names) {
  sb.append("Hello : ").append(name);
}

Resources

Benchmarks

Method Runtime Average time Error margin

append

Temurin 21

14.26 ns/op

±0.50 ns/op

concat

Temurin 21

17.77 ns/op

±0.66 ns/op

concatWithinBuilder

Temurin 21

31.42 ns/op

±1.80 ns/op

The results were generated by running the following snippet with jmh:

private String name1 = "John";
private String name2 = "Jane";

@Benchmark
public String concat() {
  return name1 + ", " + name2;
}

@Benchmark
public String concatWithinBuilder() {
  return new StringBuilder()
    .append(name1 + ", " + name2)
    .toString();
}

@Benchmark
public String append() {
  return new StringBuilder()
    .append(name1)
    .append(", ")
    .append(name2)
    .toString();
}