Text Blocks in Java

Java Text Blocks

Autor-Bild
von Sven Woltmann – 19. Januar 2022

Artikelserie: Project Amber

In Project Amber werden neue Java-Sprachfunktionen entwickelt und nach und nach veröffentlicht.

Teil 1: Switch Expressions (Java 14)

Teil 2: Text Blocks (Java 15)

Teil 3: Records (Java 16)

Teil 4: Sealed Classes (Java 17)

(Melde dich für den HappyCoders-Newsletter an,
um sofort über neue Teile informiert zu werden.)

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?

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>";
Code-Sprache: Java (java)

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>""";
Code-Sprache: Java (java)

Der Textblock 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 Textblocks müssen einzelne oder doppelte Anführungszeichen nicht escaped werden, dürfen aber (wobei SCA-Tools wie SonarLint empfehlen es nicht zu tun).
  • Möchtest du mehr als zwei Anführungszeichen schreiben, musst du jedes dritte davon escapen.

Eine der ersten Fragen, die Entwicklerinnen und Entwickler sich stellen ist:

Wie weit muss der Textblock eingerückt werden?

Die Antwort ist: es ist egal.

Der Textblock beginnt bei demjenigen Zeichen, das 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).

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""";
Code-Sprache: Java (java)

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
Code-Sprache: Klartext (plaintext)

Moderne IDEs geben uns hier eine Hilfestellung, in dem sie den linken Rand des Textblocks anzeigen (IntelliJ durch eine grüne Linie):

Darstellung des linken Randes von Java-Textblöcken in IntelliJ
Darstellung des linken Randes von Java-Textblöcken in IntelliJ

Was aber, wenn man einen Textblock 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 Textblock beginnen soll, z. B. so:

String sql = """ SELECT id, firstName, lastName FROM Employee WHERE departmentId = "IT" ORDER BY lastName, firstName """;
Code-Sprache: Java (java)

Der Textblock 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

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 Textblock einrücken kann, indem man vor die abschließenden Anführungzeichen einen Zeilenumbruch einfügt. Dieser Zeilenumbruch ist dann alerdings 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\ """;
Code-Sprache: Java (java)

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""";
Code-Sprache: Java (java)

Dieser String enthält somit nur noch einen Zeilenumbruch hinter "Employee":

SELECT id, firstName, lastName FROM Employee WHERE departmentId = "IT" ORDER BY lastName, firstName
Code-Sprache: Klartext (plaintext)

Das ist dann sinnvoll, wenn du einen einzeiligen String, z. B. ein sehr langes Log-Statement, im Quellcode mehrzeilig darstellen möchtest.

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);
Code-Sprache: Java (java)

Die Ausgabe dieses Code-Snippets lautet:

|one| |two| |three|
Code-Sprache: Klartext (plaintext)

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""";
Code-Sprache: Java (java)

Übersichtlicher und völlig ausreichend ist es, wenn wir nur das letzte Leerzeichen escapen:

String text = """ one \s two \s three \s""";
Code-Sprache: Java (java)

Somit gibt das Programm das gewünschte Ergebnis aus:

|one | |two | |three |
Code-Sprache: Klartext (plaintext)

Damit hast den den kompletten Funktionsumfang der Text Blocks kennengelernt. Viel Spaß beim Einsatz!

Geschichte der Text Blocks in Java

Text Blocks wurden erstmal durch JDK Enhancement Proposal (JEP) 355 als Preview-Feature in Java 13 vorgestellt. Sie waren ein Ersatz für den von der Community nicht akzeptierten und daraufhin zurückgezogenen JEP 326, "Raw String Literals". Falls du dich für die Gründe dahinter interessierst, du findest sie in diesem Beitrag von Brian Goetz in der jdk-dev-Mailingliste.

Im 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

Textblöcke ermöglichen es uns endlich, mehrzeilige Zeichenketten 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.

Wenn dir der Artikel gefallen hat, teile ihn gerne über einen der Share-Buttons am Ende. Setzt du Textblöcke bereits ein? Wie gefallen sie dir? Hinterlasse einen Kommentar!

Wenn du regelmäßig über neue Artikel auf HappyCoders.eu informiert werden möchtest, klicke hier, um dich für den HappyCoders-Newsletter anzumelden.