A text block is still a String. Its multiline syntax makes a report template easier to read, but delimiter placement and incidental indentation determine the exact characters you return. A closing delimiter on a new line leaves a final newline, which matters when a downstream consumer expects an exact report.
Strings are immutable; arrays aren't. A final array field only prevents assigning another array to that field. It doesn't stop a caller from changing an element through the original input or an exposed accessor. A snapshot therefore copies mutable data on both entry and exit. You can still use mutable local arrays or a StringBuilder while constructing a result. The boundary matters: callers must not be able to change the state you promised to preserve.