Short answer
Strings are immutable, so each + in a loop allocates a brand-new String and copies all prior characters, giving O(n^2) work and heavy GC pressure.
Explanation
Use StringBuilder (or StringBuffer if you truly need synchronization) to accumulate in a single resizable buffer. For simple non-loop concatenation the compiler already optimizes it — historically into StringBuilder, and since Java 9 via invokedynamic and StringConcatFactory — so manually using StringBuilder for a one-line concat is premature and less readable.
Common mistakes
- Saying + is always slow — the compiler optimises concatenation outside loops.
- Not using StringBuilder when concatenating inside a loop.