Geschichte der Frage:
Der Elvis-Operator (?:) wurde in Kotlin als prägnante und sichere Möglichkeit zur Verarbeitung von nullable-Werten eingeführt. Er erhielt seinen Namen wegen der Ähnlichkeit mit der Frisur von Elvis Presley, wenn man den Operator von der Seite betrachtet. Ziel ist es, den generischen Code wie if (a != null) a else b zu vermeiden und die tägliche Entwicklung bequemer zu gestalten.
Problem:
Direkter Zugriff auf einen Wert, der null sein kann, führt zu einem Laufzeitfehler (NullPointerException). Deshalb ist ein Werkzeug erforderlich, das es elegant ermöglicht, Standardwerte einzusetzen, wenn eine Variable null ist.
Lösung:
Der Elvis-Operator ist auf nullable-Typen anwendbar. Wenn der Ausdruck links vom Operator nicht null ist, wird er zurückgegeben, andernfalls der Ausdruck rechts. Dies macht den Code kompakter und sicherer.
Beispielcode:
fun getLength(str: String?): Int { return str?.length ?: 0 } val result = getLength(null) // result == 0 val result2 = getLength("Hello") // result2 == 5
Wichtige Merkmale:
Was passiert, wenn der Ausdruck rechts vom Elvis-Operator einen Nebeneffekt hat? Wird er immer ausgeführt?
Nein! Der Ausdruck rechts wird nur ausgewertet, wenn links null ist. Dies kann eine wichtige Rolle spielen, wenn die Funktion Nebeneffekte oder "teure" Berechnungen hat.
Beispielcode:
var called = false val x: String? = "test" val y = x ?: run { called = true; "default" } // called wird false sein, denn run wird nicht ausgeführt
Kann man den Elvis-Operator zum Auslösen von Ausnahmen verwenden?
Ja, in Kotlin kann man es so schreiben:
fun getLengthStrict(str: String?): Int = str?.length ?: throw IllegalArgumentException("str ist null")
Wenn str null ist, wird eine Ausnahme ausgelöst. Dies ist ein praktischer Mechanismus zur Validierung von Daten.
Kann man mehrere Elvis-Operatoren hintereinander "verketteten"?
Ja, dies ist ein gängiger Ansatz für Fallbacks:
val name = fromDatabase ?: fromCache ?: "Unbekannt"
Dieser Ausdruck wird den ersten NICHT null Wert oder die Zeichenkette "Unbekannt" zurückgeben.
Mehrstufige Verschachtelung von null-Prüfungen über Elvis:
val title = a?.b?.c?.d?.e ?: defaultTitle
Vorteile:
Nachteile:
Eindeutige Dekomposition in Schritten, verständliche Variablennamen:
val deepValue = a?.b val deeperValue = deepValue?.c?.d ?: default
Vorteile:
Nachteile: