Wie in Kapitel 14 festgestellt, können in der Praxis auch sog. null-Referenzen auftreten. Also Referenzen auf dem Stack, die auf kein Objekt auf dem Heap zeigen.
Man kann den Compiler konkret anweisen, null-Referenzen zuzulassen, indem man sog. nullable-Datentypen verwendet. Das geht sehr leicht. Bei der Deklaration eines Wertes ergänzt man den Datentyp einfach mit einem Fragezeigen, schon darf die Referenz auch auf null zeigen.
Problematisch sind diese Referenzen aber dann, wenn man auf sie zugreifen möchte.
In klassischem Java würde vergleichbarer Code mit einer nullPointerException abstürzen (zur Laufzeit). Das kann man gerne hier online ausprobieren. Kotlin macht aus diesem Laufzeit-Absturz einen sog. Compile-Time-Fehler, der uns sinngemäß sagt:
Wenn ich Angst haben muss, dass ich beim Folgen der Referenz auf einen null-Wert stoße, kompiliere ich dir das erst garnicht.
Es gilt also zu vermeiden, dass man eine Referenzvariable durch Funktions-Aufrufe oder Property-Zugriffe anspricht und dahinter ein Objekt erwartet, aber ein null-Wert geliefert wird, der keine dieser Aufrufe oder Zugriffe bedienen kann.
Wie kommt man dann aber an den Wert der ggf. hinter der nullbaren Referenz steckt?
Zugriff auf Nullable Types
Es gibt einige Wege, auf nullbare Referenzen zuzugreifen. Hier seien nur einige erwähnt:
Brechstange
Wenn man sich wirklich absolut sicher ist, dass hinter einer nullbaren Referenz ein Wert und eben nicht null steckt, kann man den !!-Operator verwenden. Dieser konvertiert den nullbaren Typ in einen null-sicheren Datentyp und gewährt Zugriff auf das Objekt. Falls sich doch ein null dahinter verbergen sollte, wirft das Programm zur Laufzeit (böse!) eine Exception und crasht in der Regel:
In diesem Beispiel bekommt die Klasse Person eine Property alter
mit dem nullbaren Datentyp Int?
. In der Funktion wird die Referenz auf das alter mit dem !!-Operator zwangsweise aufgerufen. Für hans
klappt das noch, da sich hinter der Referenz tatsächlich ein Wert befindet. peter
erzeugt dahingegen eine NullpointerException. Genau die galt es jedoch durch die null-sicheren Datentypen zu verhindern. Daraus folgt, dass der !!-Operator zwar sicher (selten) seinen berechtigten Einsatzzweck hat, aber man meist darauf verzichten sollte, da er den ganzen null-sicheren Entwurf der Programmiersprache zunichte macht.
Null-Checks
Man kann natürlich jede Referenz vor ihrer Verwendung überprüfen, ob sie null ist. Das ist zwar etwas umständlich und hölzern, aber dafür ziemlich sicher.
Sichere Aufrufe
Es ist auch möglich, die Aufrufe von nullbaren Typen abzusichern. Hierzu verwendet man den ?-Operator. Eine Aufrufkette, in der einmal ein ? steht gibt entweder den Wert des Aufrufs zurück, oder null.
Elvis-Operator
Der Elvis-Operator ?: bietet mir die Möglichkeit zu sagen: Wenn wir eine nullbare Referenz haben, dann verwende sie, wenn sie nicht null ist und ansonsten gib mir einen Alternativwert.
Bei diesem Beispiel sollte man besonders den Unterschied zwischen 0 und null bemerken.
Übung
Nebenstehend finden Sie ein Übungsprojekt mit Unit Tests
Ein Kommentar