Optional

Motivation

Die Tatsache, dass eine Referenz in Java auf ein Objekt zeigen kann oder null sein, macht die Programmierung für Anfänger schwierig. Aber auch Profis kämpfen mit der null-Referenz, die eine Quelle vieler Fehler sein kann. Der Erfinder dieser Referenz nennt sie rückblickend sein „billion-dollar mistake“.

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. […] I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
Tony Hoare, 2009

Andere Programmiersprachen, z. B. Ruby, haben den Fehler nicht gemacht und kennen keine null-Referenz. In Ruby gibt es zwar nil, dies ist aber ein normales Objekt, mit Methoden und Eigenschaften.

Optional

In Java kann der Datentyp Optional</code></strong> verwendet werden, um auszudrücken, dass ein Wert möglicherweise leer sein kann. Im Gegensatz zu null als leerem Wert, ist Optional eine explizite Möglichkeit, um auszudrücken, dass ein Wert nicht vorhanden sein kann und ermöglicht dadurch eine klarere und sicherere Programmierung. </p>

java.util.Optional bietet einen sicheren Ersatz für null

  • Optional.of(...)
    • erzeugt ein neues Optional mit einem Wert
    • ist der Wert null wird eine NullpointerException geworfen
  • Optional.ofNullable(...) erzeugt ein neues Optional
    • wenn das übergebene Objekt null ist, wird ein Optional.empty() zurückgegeben
    • wenn das übergebene Objekt nicht null ist, wird ein Optional.of(...) zurückgegeben
  • Optional.empty() erzeugt ein neues Optional, das leer ist
  • isPresent() prüft, ob ein Wert vorhanden ist
  • isEmpty() zeigt an, dass kein Wert vorhanden ist
  • get()
    • liest den Wert aus dem Optional aus
    • ist kein Wert vorhanden, gibt es eine Ausnahme vom Typ NoSuchElementException
  • orElse(...) führt ein get()
    • wenn kein Wert vorhanden ist, wird der übergebene Wert geliefert
    • wenn ein Wert vorhanden ist, wird dieser zurückgegeben

Optional kann verwendet werden, um die Fehleranfälligkeit in Java-Programmen zu reduzieren, indem es den Programmierer:innen ermöglicht, Fehler zu behandeln oder auszulösen, wenn ein Wert nicht vorhanden ist.

Ein weiteres Beispiel ist die Rückgabe von Werten aus einer Methode, wo ein Ergebnis nicht immer garantiert werden kann. Anstatt null zurückzugeben, könnte man eine Optional-Instanz zurückgeben, um auszudrücken, dass das Ergebnis optional ist.

## Beispielhafte Verwendung
Klasse Person
```java class Person { private Person partner; Person(Person partner) { this.partner = partner; } Person() { this(null); }; Optional getPartner() { return Optional.ofNullable(partner); } } ```

Bei dem Rückgabetyp Optional<Person> von getPartner() wird ein Typ-Parameter verwendet, weil Optional ein generischer Datentyp ist. Diese werden wir in einem späteren Kapitel betrachten. Hier muss die Information genügen, dass man durch das <Person> gestlegen kann, welchen Typ das Objekt hat, welches von Optional verwaltet wird.

Verwender
```java Person peter = new Person(); Person klaus = new Person(peter); Person hans = new Person(); System.out.println(klaus.getPartner().isPresent()); // -> true System.out.println(hans.getPartner().isPresent()); // -> false System.out.println(klaus.getPartner().get()); // -> Person@7530d0a ``` ## Primitive Datentypen

Die primitiven Datentypen nehmen in Java immer eine Sonderstellung ein. Wie bereits erläutert, kann man sie mithilfe der Wrapper-Typen in Objekte verwandeln. Dies ist aber – wegen des ständigen Ein- und Auspackens – nicht effizient. Deswegen gibt es eine Reihe von speziellen Klassen, um Optional einfach für die wichtigsten primitive Datentypen verwenden zu können.

Optional für primitive Datentypen

  • OptionalInt: Daten vom Typ int, short, byte, char
    • of(int i)
    • getAsInt()
  • OptonalLong: Daten vom Typ long
    • of(long l)
    • getAsLong()
  • OptonalDouble: Daten vom Typ float und double
    • of(double d )
    • getAsDouble()

Für die anderen Datentypen wird kein Optional angeboten, diese lassen sich aber alle problemlos in den drei vorhandenen speichern.

Im Folgenden ein Beispiel für eine Klasse Person bei der das Alter optional angegeben werden kann.

Klasse mit OptionalInt
```java class Student { private String name; private OptionalInt age; public Student(String name, int age) { this.name = name; this.age = OptionalInt.of(age); } public Student(String name) { this.name = name; this.age = OptionalInt.empty(); } public OptionalInt getAge() { return age; } } ```

Die Verwendung von OptionalInt ermöglicht es uns, klar auszudrücken, dass das Alter optional ist und dass entsprechende Maßnahmen getroffen werden müssen, um mit dieser Möglichkeit umzugehen.

Verwender
```java Person max = new Student("Max"); // Kein Alter angegeben Person anna = new Student("Anna", 25); // Alter 25 angegeben if (max.getAge().isPresent()) { System.out.println("Age: " + max.getAge().getAsInt()); } else { System.out.println("Age not available."); } ```


Copyright © 2025 Thomas Smits