skip to content

How do you control whether a text block ends with a newline, and how do the \s and trailing \ escapes work?

level: middleimportance: should knowfreq 58%

answer

  1. Closing """ on own line -> ends with \n
  2. Closing """ after last char -> no \n
  3. \s = a single space, survives stripping
  4. Trailing \ = line continuation, no newline
  5. Escapes interpreted AFTER whitespace stripping

basics

~20 s

If the closing """ is on its own line, the result ends with a newline; put the closing """ right after the last character to drop it. The \s escape preserves a trailing space, and a trailing backslash joins a line to the next (no newline).

solid answer

~50 s

A text block's trailing newline is decided by where the closing delimiter sits. If the closing """ is on a line of its own, the final content line ends in a line terminator, so the string ends with \n. If you place the closing """ immediately after the last character of content, there is no final newline. Two escapes give finer control. The \s escape (added with text blocks) is translated to a single space; because trailing whitespace is stripped before escapes are processed, \s is the idiom to force a trailing space to survive. A backslash at the very end of a line is a line-continuation: it suppresses the newline that would otherwise terminate that line, joining it to the following line — useful for wrapping a long logical line across several source lines without inserting a line break in the value.

code

java · 17 lines
java
// Trailing newline controlled by delimiter placement
String a = """
        hi
        """;      // "hi\n"
String b = """
        hi""";      // "hi"

// \s forces a trailing space to survive stripping
String c = """
        ab\s
        """;      // "ab \n"  (trailing space kept)

// trailing backslash joins lines with no newline
String d = """
        foo\
        bar
        """;      // "foobar\n"

go deeper

for a junior

Know that closing-delimiter placement controls the final newline.

for a middle

Explain \s for a forced trailing space and trailing \ for line continuation, and that the result ends in \n only when the closing delimiter is on its own line.

for a senior

Tie these behaviors to the processing order (strip whitespace before escapes) and explain why \s is necessary and how to embed literal triple-quotes.

for a principal

Set conventions for trailing-newline expectations (e.g. files ending in \n, fixed-width columns) and review-time clarity around \s/\ usage to avoid invisible-character bugs.

## Order of processing matters The compiler builds a text block's value in a fixed order: (1) normalize line terminators to `\n`, (2) strip incidental whitespace (including trailing whitespace on each line), then (3) interpret escape sequences. Because **trailing-whitespace stripping happens before escapes are read**, an escape can deliberately re-introduce whitespace that stripping would have removed. ## The trailing newline Whether the resulting String ends with a `\n` depends entirely on the closing delimiter's placement: ```java String withNewline = """ end """; // "end\n" -- closing on its own line String noNewline = """ end"""; // "end" -- closing right after the last char ``` In the first case, the line `end` is followed by a line terminator (the newline before the closing delimiter), so the value ends in `\n`. In the second case, the closing `"""` follows `end` directly, so there is no final newline. ## The `\s` escape — a forced space `\s` is a new escape sequence (introduced alongside text blocks, and also valid in ordinary string literals) that translates to a **single space character** (U+0020). Its main purpose in text blocks: since trailing whitespace is stripped *before* escapes are interpreted, you write `\s` at the end of a line to **guarantee a trailing space survives**. ```java String padded = """ red \s green\s """; ``` Here each `\s` becomes a space that the stripping pass could not remove (it was an escape, not literal trailing whitespace). It is also handy to make every line a fixed width. ## The trailing `\` — line continuation A single backslash as the **last character of a line** is a *line-continuation* escape: it suppresses the line terminator that line would otherwise contribute, so the line is joined directly to the next one with **no newline** between them. ```java String oneLine = """ The quick brown \ fox jumps """; // -> "The quick brown fox jumps\n" ``` Note there is no space inserted at the join point — if you want a space there, write it before the `\` (and protect it with `\s` if it is the last visible thing). This lets you keep a long single logical line readable in source without putting a newline in the value. ## Other escapes still work All the usual escapes (`\n`, `\t`, `\"`, `\\`, unicode `\uXXXX`) are still interpreted. Inside a text block you rarely need `\"` (a lone `"` is fine), but you do need `\"""` if you want a literal sequence of three quotes inside the block. ## Summary Closing-delimiter placement = trailing newline; `\s` = keep a trailing space; trailing `\` = drop the newline and join lines.

  • Why can't you just type a trailing space at the end of a line to keep it?
    Because the compiler strips trailing whitespace from every line before interpreting escapes. A literal trailing space is removed; \s is an escape that is applied afterward, so it survives.
  • Does a trailing backslash add a space when it joins two lines?
    No. It only suppresses the newline; the two lines are concatenated with nothing between them. Add a space (optionally as \s) yourself if you need one.
  • How do you embed a literal triple-quote sequence inside a text block?
    Escape at least one of the quotes, e.g. \""" , so the compiler doesn't read it as the closing delimiter.

saying these in an interview costs you the question

  • Thinking \s inserts a newline or tab rather than a space
  • Believing a trailing space survives without \s (it is stripped)
  • Claiming trailing \ inserts a space at the join (it does not)
  • Saying escapes are processed before whitespace stripping

context