Der sichere Aufrufoperator '?.' ist eines der wichtigsten Werkzeuge zur Vermeidung von Nullwerten in Kotlin und entstand als Weiterentwicklung der Ideen einer Sprache, die darauf abzielt, die Sicherheit und Benutzerfreundlichkeit im Umgang mit potenziell fehlenden Werten zu erhöhen.
Hintergrund: In Java sind Nullwerte oft eine Quelle von Fehlern (NullPointerException). Kotlin führte ein strenges Typsystem ein, das Nullable- und Not-Nullable-Variablen klar unterscheidet, und begleitete dies mit Werkzeugen zu deren benutzerfreundlicher Nutzung.
Problem: Wie kann man NullPointerException beim Umgang mit Objekten vermeiden, die null sein könnten, ohne die Lesbarkeit und Eleganz des Codes zu opfern?
Lösung: Der Operator '?.' ermöglicht einen behutsamen Zugriff auf die Eigenschaften und Methoden von Nullable-Variablen: Wenn das Objekt nicht null ist, erfolgt der Aufruf, wenn es null ist — wird null zurückgegeben (oder andere nötige Logik wird weiter verfolgt).
Beispielcode:
val user: User? = getUser() val name = user?.name // wenn user != null, wird user.name zurückgegeben, sonst null user?.printInfo() // wenn user != null, wird printInfo() aufgerufen
Wichtige Eigenschaften:
Kann der sichere Aufrufoperator '?.' links vom Zuweisungsoperator verwendet werden?
Nein. Der Operator '?.' kann nicht zur sicheren Zuweisung von Werten an Eigenschaften oder Variablen verwendet werden; er dient nur dem Zugriff oder Aufruf. Folgendes ist inkorrekt:
user?.name = "Alex" // Kompilierungsfehler
Die Zuweisung von Eigenschaften kann sicher durch eine explizite Überprüfung erfolgen:
user?.let { it.name = "Alex" }
Was gibt eine Kette von sicheren Aufrufoperatoren bei der ersten Begegnung mit null zurück?
Sobald eines der Elemente in der Kette '?.' null ist, wird das Ergebnis des Ausdrucks null, weitere sichere Aufrufe werden nicht ausgeführt.
Beispiel:
user?.address?.zipCode // wenn user oder address == null, ist das Ergebnis null
Kann der sichere Aufruf '?.' mit Funktionen verwendet werden, die Unit zurückgeben?
Ja, der Aufruf erfolgt trotzdem nur, wenn das Objekt nicht null ist, andernfalls wird null anstelle von Unit zurückgegeben, wenn das Objekt null ist.
Beispiel:
user?.clearData() // wenn user == null, passiert nichts
Ein Entwickler verwendet '!!' dort, wo das Objekt null sein könnte, nach einer langen Kette sicherer Aufrufe:
val country = user?.address?.city?.country!!
Vorteile:
Nachteile:
Der sichere Aufruf wird gemeinsam mit dem Elvis-Operator verwendet, um einen Standardwert zurückzugeben:
val country = user?.address?.city?.country ?: "Unknown"
Vorteile:
Nachteile: