Für eine kleine Ewigkeit

Java 11 – eine Einführung: Neue Hilfsmethoden in der Klasse String und der Utility-Klasse Files

Michael Inden

© Shutterstock / Profit_Image

Java 11 steht seit Ende September 2018 zum Download bereit und stellt nach Java 8 wieder ein sogenanntes LTS-Release (Long Time Support) dar. Das ist insofern erfreulich, da hier einige Jahre Support und Updates angeboten werden, wohingegen Java 9 und 10 durch die neue Release-Politik von Oracle jeweils lediglich für eine kurze Zeitspanne von 6 Monaten aktuell waren und auch keine Updates mehr erhalten. In seiner neuen Serie zu Java 11 gibt Michael Inden einen Einblick in die Features der neuen Java-Version.

Michael Inden hat bereits die Highlights von Java 9 in seiner Artikelserie Java 9 – Eine Einführung vorgestellt, in der Serie Best of Java 10 ging er auf die Neuerungen in Java 10 ein. Die vorliegende Artikelserie setzt sich aus Texten zusammen, die auch Teil seines neuen Buches zu Java 10/11 sein werden, das beim dpunkt.verlag erscheinen wird.

Nachdem es im vorherigen Teil der Serie um die Syntax-Erweiterung für var ging, starten wir diesmal mit den Neuerungen in diversen APIs von Java 11. Im Bereich der API-Neuerungen ist einiges erwähnenswert: Zunächst gehe ich auf die neuen Methoden in der Klasse java.lang.String ein. Danach zeige ich verschiedene Convenience-Funktionalitäten, als erstes in der Utility-Klasse java.nio.file.Files. Im darauf folgenden Serienteil stelle ich eine kleinere Erweiterung in der Klasse java.util.Optional<T> vor. Eine solche findet sich auch in den Klassen java.util.function.Predicate<T> sowie in java.util.concurrent.Time-Unit. Beide Neuerungen behandle ich in separaten Abschnitten. Abschließend stelle ich das HTTP/2-API vor, das mit Java 11 den Incubator-Status verlassen hat und zum vollwertigen API in das JDK aufgenommen wurde.

Neue Hilfsmethoden in der Klasse String

Die Klasse java.lang.String existiert seit JDK 1.0 und hat zwischenzeitlich nur wenige API-Änderungen erfahren. Mit Java 11 ändert sich das – es wurden folgende Methoden neu eingeführt:

  • isBlank()
  • lines()
  • repeat(int)
  • strip()
  • stripLeading()
  • stripTrailing()

Schauen wir uns zum besseren Verständnis im Anschluss einfache Beispiele für diese an.

Die Methode isBlank()

Für Strings war es bisher mühsam oder nur mithilfe von externen Bibliotheken möglich, zu prüfen, ob diese nur Whitespaces enthalten. Als Abhilfe wurde mit Java 11 die Methode isBlank() eingeführt, die sich auf Character.isWhitespace(int) stützt. Folgendes Beispiel demonstriert die Prüfung auf einen leeren oder nur Whitespace enthaltenden String:

private static void isBlankExample()
{
    final String exampleText1 = "";
    final String exampleText2 = " ";
    final String exampleText3 = " \n \t ";

    System.out.println(exampleText1.isBlank());
    System.out.println(exampleText2.isBlank());
    System.out.println(exampleText3.isBlank());
}

Alle drei geben true aus.

Die Methode lines()

Beim Verarbeiten von Daten aus Dateien müssen des Öfteren Informationen in einzelne Zeilen aufgebrochen werden. Dazu gibt es etwa die Methode Files.lines(Path). Ist die Datenquelle allerdings schon ein String, existierte diese Funktionalität bislang noch nicht. Mit JDK 11 finden wir in der Klasse String die Methode lines(), die einen Stream<String> zurückliefert und wie folgt genutzt werden kann:

private static void linesExample()
{
    final String exampleText = "1 This is a\n2 multi line\n" +
                               "3 text with\n4 four lines!";

    final Stream<String> lines = exampleText.lines();
    lines.forEach(System.out::println);
}

Diese Methode unterteilt den mehrzeiligen String in vier einzelne Bestandteile und gibt somit Folgendes aus:

1 This is a
2 multi line
3 text with
4 four lines!

Die Methode repeat(int)

Immer mal wieder steht man vor der Aufgabe, einen String mehrmals aneinanderzureihen, also einen bestehenden String n-Mal zu wiederholen. Dazu waren bislang eigene Hilfsmethoden oder solche aus externen Bibliotheken nötig. Mit Java 11 kann man stattdessen die Methode repeat(int) nutzen, wie es folgendes Beispiel zeigt:

private static void repeatExample()
{
    final String star = "*";
    System.out.println(star.repeat(30));

    final String delimeter = " -*- ";
    System.out.println(delimeter.repeat(6));
}

Die obige Methode produziert diese Ausgaben:

******************************
 -*- -*- -*- -*- -*- -*-
Tipp: Spezialfälle

Die beiden zuvor gezeigten Beispiele wirken ganz natürlich. Zwei Dinge könnte man sich noch fragen:

  1. Was passiert, wenn man den Wert 0 übergibt? Dann entsteht ein leerer String.
  2. Was passiert, wenn man einen leeren String extrem oft, etwa eine Million Mal oder gar Integer.MAX_VALUE Male wiederholt? Auch dann entsteht konsequenterweise ein leerer String.

Die Methoden strip(), stripLeading() und stripTrailing()

Mit der seit JDK 11 neuen Methode strip() lassen sich aus einem String führende und nachfolgende Leerzeichen (Whitespaces) entfernen. Aber gibt es dazu nicht schon die Methode trim()? Eigentlich ja, aber trim() nutzt eine leicht abweichende Definition von Whitespace. Die Methode strip() stützt sich – wie isBlank() – auf Charater.isWhitespace(int). Gleiches gilt auch für die beiden Methoden stripLeading() und stripTrailing(). Erstere entfernt Whitespace nur am Anfang, letztere nur am Ende eines Strings. Nachfolgendes Beispiel demonstriert diese Methoden:

private static void stripExample()
{
    final String exampleText1 = " abc ";
    final String exampleText2 = " \t XYZ \t ";

    System.out.println("’" + exampleText1.strip() + "’");
    System.out.println("’" + exampleText2.strip() + "’");
    System.out.println("’" + exampleText2.stripLeading() + "’");
    System.out.println("’" + exampleText2.stripTrailing() + "’");
}

Schauen wir uns die Resultate an:

’abc’
’XYZ’
’XYZ     ’
’    XYZ’

Neue Hilfsmethoden in der Utility-Klasse Files

In Java 11 wurde die Verarbeitung von Strings im Zusammenhang mit Dateien erleichtert. Es ist nun einfach möglich, Strings in eine Datei zu schreiben bzw. daraus zu lesen. Dazu hat die Utility-Klasse java.nio.file.Files ein paar Erweiterungen in Form der Methoden writeString() und readString() erhalten. Folgendes Beispiel zeigt das Schreiben bzw. Lesen eines Strings, wobei standardmäßig von UTF-8 als Kodierung ausgegangen wird:

var destinationPath = Path.of("ExampleFile.txt");

Files.writeString(destinationPath, "1: This is a string to file test\n");
Files.writeString(destinationPath, "2: Second line");

final String line1 = Files.readString(destinationPath);
final String line2 = Files.readString(destinationPath);

System.out.println(line1);
System.out.println(line2);

Führt man dieses Programmfragment aus, so erwartet man vermutlich die beiden in die Datei geschriebenen Zeilen als Ausgabe, doch man erhält abweichend folgende Ausgabe:

2: Second line
2: Second line

Wie kommt das? Die Antwort ist relativ einfach: Beim Schreiben wird nicht ganz überraschungsfrei der Modus des Überschreibens und nicht des Anhängens genutzt. Modifizieren wir den Source Code minimal wie folgt:

Files.writeString(destinationPath, "1: This is a string to file test\n");
Files.writeString(destinationPath, "2: Second line", StandardOpenOption.APPEND);

var line1 = Files.readString(destinationPath);
var line2 = Files.readString(destinationPath);

Führen wir das Ganze nochmals aus, so könnte die Ausgabe wiederum überraschen:

1: This is a string to file test
2: Second line
1: This is a string to file test
2: Second line

Wir erkennen daran, dass nun die gesamte Datei als eine Zeile eingelesen wird. Somit spannt sich der Bogen zu String.lines(), womit wir dann folgende Korrektur vornehmen:

var destinationDath = Path.of("AppendExampleFile.txt");

Files.writeString(destinationPath, "1: This is a string to file test\n");
Files.writeString(destinationPath, "2: Second line", StandardOpenOption.APPEND);

var content = Files.readString(destinationPath);

content.lines().forEach(System.out::println);

Dadurch erhalten wir dann die erwartete Ausgabe:

1: This is a string to file test
2: Second line

Im nächsten Teil der Serie geht es dann um die Eweiterungen in den Klassen Optional, Predicate und TimeUnit!

Der Weg zum Java-Profi

Michael Indens Buch bietet eine umfassende Einführung in die professionelle Java-Entwicklung und vermittelt Ihnen das notwendige Wissen, um stabile und erweiterbare Softwaresysteme auf Java-SE-Basis zu bauen. Praxisnahe Beispiele helfen dabei, das Gelernte rasch umzusetzen. Neben der Praxis wird viel Wert auf das Verständnis zugrunde liegender Konzepte gelegt.

Die Neuauflage wurde durchgehend überarbeitet, aktualisiert und erweitert. Auch Java 9 sind zwei Kapitel gewidmet. Eine neue Auflage des Buches mit Erweiterungen für aktuellere Java-Versionen ist für den Sommer bzw. Herbst 2019 geplant.

Weitere Informationenen zum Buch gibt es hier!

Verwandte Themen:

Geschrieben von
Michael Inden
Michael Inden
Dipl.-Inform. Michael Inden ist Oracle-zertifizierter Java-Entwickler für JDK 6. Nach seinem Studium in Oldenburg war er lange Zeit als Softwareentwickler und -architekt bei verschiedenen internationalen Firmen tätig und arbeitet derzeit als Teamleiter Softwareentwicklung in Zürich. Michael Inden hat rund 20 Jahre Erfahrung beim Entwurf komplexer Softwaresysteme gesammelt, an diversen Fortbildungen und an mehreren Java-One-Konferenzen in San Francisco teilgenommen. Sein Wissen gibt er gerne als Trainer in Schulungen und auf Konferenzen weiter. Sein besonderes Interesse gilt dem Design qualitativ hochwertiger Applikationen mit ergonomischen, grafischen Oberflächen sowie dem Coaching von Kollegen.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu: