NULL-Werte ohne Ausnahmen
Welcher Softwareentwickler kennt das nicht?
Trotz des Gesetz von Demeter kommt es immer wieder vor, dass man eine Methode an einem Objekt aufrufen möchte, welches man selbst wiederum erst durch einen Methodenaufruf erhalten hat.
Ein typisches Beispiel hierfür ist die Abfrage der Postleitzahl der Adresse einer Person, um beispielsweise Briefe für einen optimierten Versand nach den Postleitzahlen sortiert zu drucken.
In Java
würde das dann etwa so aussehen:
public PlzType getPlzForPerson(Person person) {
return person.getAddress().getPLZ();
}
Das Problem dabei: Angefangen vom übergebenen Objekt person
können alle Zwischenergebnisse dieser Kette von Aufrufen möglicherweise leer sein, also null
.
Um hier keine NullPointerException
(sog. NPE) zu erhalten, muss man also alle Werte prüfen und endet damit bei deutlich komplexerem Code, selbst bei unserem kleinen
Beispiel mit nur zwei aufeinanderfolgenden Methodenaufrufen in der Kette:
public PlzType getPlzForPerson(Person person) {
if (person == null)
return null;
else if (person.getAdress() == null)
return null;
else
return person.getAddress().getPLZ();
}
Seit der Einführung der Klasse Optional
in Java 8
gibt es jedoch eine
Möglichkeit, die Behandlung von null
-Werten in solchen Methodenketten um einiges kompakter zu formulieren:
public PlzType getPlzForPerson(Person person) {
Optional.ofNullable(person).
map(Person::getAddress).
map(Address::getPLZ).
orElse(null);
}
Anstelle von null
geben die map
-Methoden von Optional
einfach ein leeres Optional
-Objekt zurück. orElse
gibt dann am Ende den Inhalt des Optional
zurück,
oder eben den hier angegebenen Default-Wert.
Statt des abschließenden orElse
, welches den Rückgabewert im Falle eines null
irgendwo in der Aufrufkette festlegt, kann man auch die Methoden
orElseGet
(Aufruf einer anderen Funktion) oder orElseThrow
(werfen einer Exception) verwenden.
Die ebenfalls auf der JVM (Java Virtual Machine) basierende Programmiersprache Kotlin
vermeidet
das Problem der NullPointerException
weitestgehend, indem sie null
zunächst einmal gar nicht als Wert einer Variable zulässt.
Man kann allerdings Variablen auch in Kotlin
explizit als nullable deklarieren, zudem können sich null
-Werte natürlich auch durch die Interaktion mit
Java-Code einschleichen.
Die Sprache macht den Zugriff dann aber mit ihrem Safe Call Operator recht einfach und elegant:
person?.address?.plz
Zudem kann mit Hilfe der Nutzung des Elvis-Operators ?:
ebenfalls ein Default-Wert angegeben werden.
Ähnliche Mechanismen gibt es auch in vielen anderen Programmiersprachen, beispielsweise in Ruby
.
Seit der Ruby-Version 2.3.0 kann man mit Hilfe des Safe Navigation Operator anstatt
person.address.plz if person && person.plz
auch einfach
person&.address&.plz
schreiben.
Eine Übersicht zum Safe Navigation Operator in verschiedenen Sprachen ist auf Wikipedia zu finden.
Der Erfinder der null
-Referenz, C.A.R. Hoare, hat sich übrigens 2009 auf einer Software-Konferenz
bei der Community für diesen Billion Dollar Mistake offiziell entschuldigt.