
In Java 15 wurden im Rahmen von Project Amber Text Blocks (mehrzeilige Strings) eingeführt.
In diesem Artikel erfährst du:
- Warum brauchen wir Text Blocks?
- Wie notiert man Text Blocks in Java?
- Wie muss ein Text Block eingerückt werden?
- Welche Escape-Sequenzen kann bzw. muss man im Text Block verwenden?
- Wie setzt du Werte in einen Text Block ein?
Mehrzeilige Strings in Java
Wenn wir vor Java 15 einen mehrzeiligen String notieren wollten, sah das in der Regel so aus:
String sql =
" SELECT id, firstName, lastName\n"
+ " FROM Employee\n"
+ " WHERE departmentId = \"IT\"\n"
+ "ORDER BY lastName, firstName";
String html =
"<html>\n"
+ " <body>\n"
+ " <p>Hello World!</p>\n"
+ " </body>\n"
+ "</html>";
Zeilenumbrüche und Anführungszeichen mussten wir durch Escape-Sequenzen (\n und \") ersetzen. Und um den String einigermaßen leserlich auf mehrere Zeilen aufzuteilen, mussten wir ihn unterteilen und mit + wieder konkatenieren. Schlimm war das nicht (da der Compiler wieder einen einzigen String daraus machte), aber schön war es auch nicht.
Text Block Notation
Ab Java 15 können wir mehrzeilige Strings als „Text Blocks“ notieren:
String sql = """
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName""";
String html = """
<html>
<body>
<p>Hello World!</p>
</body>
</html>""";
Der Text Block startet und endet mit jeweils drei Anführungszeichen. Es gelten folgende Regeln:
- Hinter den startenden Anführungszeichen muss ein Zeilenumbruch folgen; dieser wird nicht Teil des Strings.
- Wenn vor den endenden Anführungszeichen ein Zeilenumbruch erfolgt, ist dieser Zeilenumbruch Teil des Strings.
- Innerhalb des Text Blocks müssen einzelne oder doppelte Anführungszeichen nicht escaped werden, dürfen aber (wobei Tools zur statischen Code-Analyse wie SonarQube empfehlen, es nicht zu tun).
- Möchtest du mehr als zwei Anführungszeichen hintereinander schreiben, musst du jedes dritte davon escapen.
- Steht ein Anführungszeichen direkt vor den schließenden
""", musst du es escapen:\".
Eine der ersten Fragen, die Entwickler:innen sich stellen, ist:
Wie weit muss der Text Block eingerückt werden?
Die Antwort ist: Es ist egal.
Der Text Block beginnt bei dem Zeichen, das in einer der nicht leeren Zeilen am weitesten links steht (im ersten Beispiel oben bei dem „O“ von „ORDER BY“ bzw. im zweiten Beispiel bei den spitzen Klammern in der ersten und letzten Zeile). Stehen die schließenden Anführungszeichen allein auf ihrer Zeile, zählen sie mit – dazu gleich mehr.
Die folgenden drei Notationen führen alle zu demselben Ergebnis:
String sql1 = """
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName""";
String sql2 = """
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName""";
String sql3 = """
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName""";
Alle drei Strings haben – unabhängig von der Einrückung im Quellcode – den folgenden Inhalt:
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName
Moderne IDEs geben uns hier eine Hilfestellung, indem sie den linken Rand des Text Blocks anzeigen (IntelliJ durch eine grüne Linie):

Die Leerzeichen links vom Rand des Text Blocks gehören zum sogenannten Incidental Whitespace: Sie stammen aus der Einrückung des Quellcodes, und der Compiler entfernt sie. Die Leerzeichen rechts vom Rand – im Beispiel die zwei vor „SELECT“, die vier vor „FROM“ und die drei vor „WHERE“ – sind Essential Whitespace: Sie gehören zum Inhalt und bleiben im String erhalten.
Was aber, wenn man einen Text Block erstellen möchte, der eingerückt ist?
Dafür gibt es einen Trick: Du fügst vor den abschließenden Anführungszeichen einen Zeilenumbruch ein und setzt die Anführungszeichen an die Stelle, an der der Text Block beginnen soll, z. B. so:
String sql = """
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName
""";
Der Text Block ist nun um zwei Zeichen eingerückt.
Allerdings hat er am Ende auch einen Zeilenumbruch. Diesen können wir mit einer Escape-Sequenz wieder entfernen. Escape-Sequenzen werden im folgenden Kapitel behandelt.
Escape-Sequenzen in Text Blocks
Der Compiler verarbeitet den Inhalt eines Text Blocks in drei Schritten: Zuerst normalisiert er die Zeilenenden. Aus CR und CRLF wird LF – ein unter Windows gespeicherter Text Block enthält also kein \r\n. Dann entfernt er das incidental Whitespace, d. h. die gemeinsame Einrückung links und die Leerzeichen am Zeilenende. Erst zuletzt wertet er die Escape-Sequenzen aus.
Das folgende Diagramm zeigt die drei Schritte in dieser Reihenfolge und zu jedem Schritt, was sich darin ändert:
Text Blocks haben den Vorteil, dass die in Strings am häufigsten verwendeten Escape-Sequenzen, nämlich \" für Anführungszeichen und \n für einen Zeilenumbruch, nicht mehr benötigt werden.
Stattdessen gibt es zwei neue Escape-Sequenzen:
Escape-Sequenz: Backslash am Zeilenende
Im vorherigen Kapitel hast du gesehen, dass man einen Text Block einrücken kann, indem man vor die abschließenden Anführungszeichen einen Zeilenumbruch einfügt. Dieser Zeilenumbruch ist dann allerdings auch im String enthalten. Um ihn zu entfernen, kannst du an das Ende der letzten Zeile einen Backslash setzen:
String sql = """
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName, firstName\
""";
Der Backslash am Zeilenende sorgt dafür, dass der String an dieser Stelle keinen Zeilenumbruch enthält.
Diese Funktion ist nicht auf die letzte Zeile beschränkt – du kannst jede beliebige Zeile mit einem Backslash enden lassen, wie in folgendem Beispiel:
String sql = """
SELECT id, firstName, lastName \
FROM Employee
WHERE departmentId = "IT" \
ORDER BY lastName, firstName""";
Dieser String enthält somit nur noch einen Zeilenumbruch hinter „Employee“:
SELECT id, firstName, lastName FROM Employee
WHERE departmentId = "IT" ORDER BY lastName, firstName
Das ist dann sinnvoll, wenn du einen einzeiligen String, z. B. ein sehr langes Log-Statement, im Quellcode mehrzeilig darstellen möchtest.
Diese Escape-Sequenz gibt es nur in Text Blocks – in einem gewöhnlichen String-Literal meldet der Compiler „illegal escape character“.
Escape-Sequenz: \s
Eine weitere Escape-Sequenz, mit der du einen Text Block formatieren kannst, ist \s.
Abschließende Leerzeichen werden standardmäßig aus jeder Zeile entfernt, wie in folgendem Beispiel (die Punkte sollen Leerzeichen darstellen):
String text = """
one·····
two·····
three···""";
text.lines().map(line -> "|" + line + "|").forEachOrdered(System.out::println);
Die Ausgabe dieses Code-Snippets lautet:
|one|
|two|
|three|
Um die Leerzeichen zu erhalten, kannst du diese durch die Escape-Sequenz \s ersetzen:
String text = """
one\s\s\s\s\s
two\s\s\s\s\s
three\s\s\s""";
Übersichtlicher und völlig ausreichend ist es, wenn wir nur das letzte Leerzeichen escapen:
String text = """
one \s
two \s
three \s""";
Somit gibt das Programm das gewünschte Ergebnis aus:
|one |
|two |
|three |
\s funktioniert übrigens auch in gewöhnlichen String-Literalen: "a\sb" ergibt a b.
Die drei neuen String-Methoden
Mit den Text Blocks sind drei neue Methoden in die Klasse String gekommen – alle seit Java 15:
formatted(Object... args)setzt Werte in den String ein. Sie entsprichtString.format(text, args), steht aber hinter dem Text Block, was oft besser lesbar ist.stripIndent()entfernt das incidental Whitespace eines mehrzeiligen Strings, also die gemeinsame Einrückung und die Leerzeichen am Zeilenende – mit demselben Algorithmus, den der Compiler auf Text Blocks anwendet.translateEscapes()wertet Escape-Sequenzen aus, die als Text in einem String stehen, z. B. ein aus einer Datei gelesenes\n.
Am häufigsten brauchst du formatted(), denn ein Text Block kann keine Variablen einbetten – eine String-Interpolation gibt es in Java nicht. Das folgende Beispiel setzt die Abteilung und das Sortierfeld in die SQL-Abfrage ein:
String sql = """
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "%s"
ORDER BY %s""".formatted("IT", "lastName");
Der String sql enthält danach:
SELECT id, firstName, lastName
FROM Employee
WHERE departmentId = "IT"
ORDER BY lastName
Geschichte der Text Blocks in Java
Text Blocks wurden erstmals durch JDK Enhancement Proposal (JEP) 355 als Preview-Feature in Java 13 vorgestellt. Sie folgten auf JEP 326, „Raw String Literals“, den Jim Laskey und Brian Goetz noch vor dem Release von Java 12 zurückgezogen hatten: Nach dem Feedback auf den Entwurf hielten sie das Design nicht mehr für reif genug für eine Preview. Ihre Gründe stehen im Beitrag von Brian Goetz in der jdk-dev-Mailingliste.
In der zweiten Preview, JEP 368, wurden in Java 14 die o. g. Escape-Sequenzen hinzugefügt.
Aufgrund des positiven Feedbacks wurden Text Blocks in Java 15 durch JEP 378 ohne weitere Änderungen als produktionsreifes Feature veröffentlicht.
Fazit
Text Blocks ermöglichen es uns endlich, mehrzeilige Strings in Java-Code komfortabel zu notieren. Sie werden in dreifache Anführungszeichen eingeschlossen. Anführungszeichen und Zeilenumbrüche müssen nicht mehr durch unübersichtliche Escape-Sequenzen ersetzt werden.
Werte setzt du mit formatted() ein – eine String-Interpolation gibt es in Java auch 2026 nicht.
Hat dir dieser Artikel Zeit gespart? Dann freue ich mich, wenn du eine Minute davon in eine Bewertung auf meinem ProvenExpert-Profil investierst. Dein Feedback zeigt mir, dass sich die Arbeit an diesen Artikeln lohnt.




