JB Header

Java Text Blocks: Multi-line Strings with Examples

Introduction Writing HTML, JSON, SQL or a long message as an ordinary string literal means a jumble of \n escapes, escaped quotes and + signs. Text blocks, standard since Java 15, let you write multi-line text exactly as it should look. This tutorial explains Java text blocks with examples. We will start with the problem they solve, and the syntax of a text block. We will then understand how Java removes the indentation that only exists to line the text up with your code. Next we will look at the escape sequences for text blocks - including joining lines and keeping trailing spaces. Lastly, we will fill values into a text block, and go through common uses and mistakes.

(Note - Ordinary string literals and escape sequences are covered in Java LiteralsClick to read tutorial: Java Literals: Integer, Floating-Point, char and boolean.) The problem with multi-line string literals
A JSON string the old way
String json = "{\n" +
              "  \"name\": \"Tom\",\n" +
              "  \"city\": \"London\"\n" +
              "}";
Every line needs an escaped newline, every quote needs a backslash, and every line needs a +. The text is hard to read and easy to break. Syntax of a text block A text block starts with three double quotes """ followed by a line break, and ends with three double quotes. Everything between them is the string - line breaks and double quotes included, with no escaping needed.
A text block
//TextBlockBasics.java
public class TextBlockBasics {
  public static void main(String[] args) {
    String oldWay = "{\n" +
                    "  \"name\": \"Tom\",\n" +
                    "  \"city\": \"London\"\n" +
                    "}\n";

    String json = """
        {
          "name": "Tom",
          "city": "London"
        }
        """;

    System.out.print(json);
    System.out.println("Same as the old way: " + json.equals(oldWay));
    System.out.println("It is an ordinary String of length " + json.length());
  }
}
 OUTPUT of the above code
{
  "name": "Tom",
  "city": "London"
}
Same as the old way: true
It is an ordinary String of length 40
Explanation of the code
  • The opening """ must be followed by a line break - the content starts on the next line. String s = """Hello"""; does not compile.
  • A text block is just another way of writing a String literal. The result is an ordinary String, equal to the old version, and it is pooled like any literal.
  • Because the closing """ is on its own line, the string ends with a line break. That is why the example used print(), not println().
How indentation is removed The text block above is indented in the source code to line up with the rest of the method, but that indentation is not part of the string. Java removes it automatically -
  1. It looks at every non-blank line, and the line with the closing """.
  2. It finds the smallest number of leading spaces among them - the common indentation.
  3. It removes that many spaces from the start of every line. Indentation beyond the common amount is kept.
  4. It also removes trailing spaces at the end of every line.
So the position of the closing """ controls the indentation. Moving it to the left keeps extra spaces in the string; putting it at the end of the last line means the string does not end with a line break.
The closing delimiter controls indentation
//Indentation.java
public class Indentation {
  public static void main(String[] args) {
    String flush = """
        line one
          line two
        """;
    String indented = """
        line one
          line two
    """;
    String noNewline = """
        line one
          line two""";

    System.out.print("[flush]\n" + flush);
    System.out.print("[indented]\n" + indented);
    System.out.println("[noNewline]\n" + noNewline + "<- string ends here");
  }
}
 OUTPUT of the above code
[flush]
line one
  line two
[indented]
    line one
      line two
[noNewline]
line one
  line two<- string ends here
Explanation of the code
  • In flush, the closing """ lines up with the text, so the text starts at the left edge. The extra two spaces of line two are kept, as they are beyond the common indentation.
  • In indented, the closing """ is four spaces further left, so four spaces stay at the start of each line.
  • In noNewline, the closing """ follows the text directly, so there is no line break at the end.
Escape sequences in text blocks All the usual escape sequences work in text blocks. Two more are especially useful -
  • \ at the end of a line - joins the line with the next one, without a line break. It lets you wrap a long single line in the source.
  • \s - a single space which is never stripped. Use it to keep trailing spaces, which are otherwise removed.
  • \""" - three quotes inside a text block need one of them escaped.
Escape sequences in text blocks
//TextBlockEscapes.java
public class TextBlockEscapes {
  public static void main(String[] args) {
    String longLine = """
        This sentence is far too long to fit on one line of source code, \
        so it is wrapped in the source but stays one line in the string.""";
    System.out.println(longLine);

    String table = """
        Name \s
        Tom  \s
        """;
    System.out.println(table.replace(' ', '.'));

    String quotes = """
        She said "Hello", and wrote \""" on the board.""";
    System.out.println(quotes);
  }
}
 OUTPUT of the above code
This sentence is far too long to fit on one line of source code, so it is wrapped in the source but stays one line in the string.
Name..
Tom...

She said "Hello", and wrote """ on the board.
Replacing spaces with dots makes them visible: the spaces before each \s, and the \s itself, were kept at the end of the lines.
Filling in values - formatted() Text blocks have no built-in way of inserting variables, but they work naturally with formatted() (Java 15+), which uses the same format specifiers as printf and String.formatClick to read tutorial: Java Console Output: println, printf and String.format.
A text block used as a template
//TextBlockTemplate.java
public class TextBlockTemplate {
  public static void main(String[] args) {
    String template = """
        <div class="card">
          <h2>%s</h2>
          <p>Order #%05d - total %.2f</p>
        </div>
        """;
    System.out.print(template.formatted("Tom Jones", 317, 98.5));

    String sql = """
        SELECT id, name
        FROM customers
        WHERE city = ?
        ORDER BY name""";
    System.out.println(sql);
  }
}
 OUTPUT of the above code
<div class="card">
  <h2>Tom Jones</h2>
  <p>Order #00317 - total 98.50</p>
</div>
SELECT id, name
FROM customers
WHERE city = ?
ORDER BY name
Note - For SQL, put values in with ? placeholders and a PreparedStatement, as above, never by formatting user input into the query text - that would open the door to SQL injection. Common uses and mistakes
  • Good uses: JSON, XML and HTML snippets, SQL queries, test data, help and usage messages, and any text which is easier to read laid out as it will appear.
  • Content on the opening line: text after the opening """ on the same line is a compile error.
  • An unexpected final line break: if the closing """ is on its own line, the string ends with \n. Put it right after the last line of text if you do not want that.
  • Mixing tabs and spaces: indentation is counted in characters, so a tab counts as one. Use spaces only in text blocks to get predictable results.
  • Line endings: line breaks in a text block are always \n, even if the source file uses Windows \r\n line endings.
Summary In this tutorial we first saw how awkward multi-line text is with ordinary string literals. We then wrote text blocks, which start with """ and a line break, and produce ordinary Strings. Next we learned how Java removes the common indentation, and how the position of the closing """ controls indentation and the final line break. We then used the text block escapes - \ to join lines, \s to keep spaces, and \""" for triple quotes. Lastly, we filled values into text blocks with formatted(), and went through common uses and mistakes. In the next tutorial, we will practise with common string programsClick to read tutorial: Common Java String Programs with Examples.