Elvis Operator — to operator binarny, który zwraca lewy operand, jeśli nie jest null, a prawy w przeciwnym razie. Zapisuje się go jako ?: w Kotlin, Groovy i niektórych innych językach. Według Kotlin Language Documentation, 2024, operator jest częścią systemu null-bezpieczeństwa języka i pozwala skrócić konstrukcje warunkowe do jednej linii bez utraty czytelności. W przeciwieństwie do pełnego zapisu if-else, Elvis Operator oblicza prawą część tylko przy wartości null lewej, co daje przewagę wydajnościową przy użyciu kosztownych wyrażeń domyślnych.
Najważniejsze
Elvis Operator — operator binarny nazwany na cześć fryzury Elvisa Presleya. Symbol ?: wizualnie przypomina twarz piosenkarza z profilu: znak zapytania to oko i bokobrody, dwukropek to usta. Operator przyjmuje dwa operandy: jeśli pierwszy nie jest null — zwracany jest on, w przeciwnym razie zwracany jest drugi. Pozwala to zastąpić pełną konstrukcję if-else jednym krótkim zapisem.
Nazwa „Elvis Operator” utrwaliła się w społeczności Kotlin i Groovy, a następnie przeszła do Xtend i innych języków JVM. W Swift i Dart podobna konstrukcja nazywa się nil-coalescing operator, ale funkcjonalnie jest identyczna. Wizualne skojarzenie z Elvisem Presleyem pomogło operatorowi stać się jednym z najbardziej rozpoznawalnych symboli w składni nowoczesnych języków programowania.
Elvis Operator — część systemu null safety, zapobiegającego NullPointerException (NPE). Według badania JetBrains z 2023 roku, NPE stanowi 28% wszystkich wyjątków w kodzie produkcyjnym na JVM. Użycie Elvis Operator całkowicie eliminuje NPE w miejscu przypisania, gwarantując wartość domyślną. W połączeniu z operatorem bezpiecznego wywołania ?. otrzymujemy niezawodny łańcuch bez ani jednego bloku if.
W Kotlin Elvis Operator zapisuje się jako ?: między dwoma wyrażeniami. Jeśli lewe wyrażenie nie jest null — wynik jest równy lewemu, w przeciwnym razie obliczane jest prawe. Prawe wyrażenie jest obliczane leniwie — tylko gdy lewy operand jest null, co jest ważne dla wydajności przy użyciu kosztownych obliczeń lub wywołań API.
val name: String? = getUserName()
val displayName = name ?: "Guest"
fun getLength(str: String?): Int {
return str?.length ?: 0
}
val config: Config? = loadConfig()
val timeout = config?.timeout ?: 30
println("Limit czasu: $timeout")
// Elvis z throw dla wymaganych parametrów
val requiredId = nullableId ?: throw IllegalArgumentException("ID is required")
// Elvis z return dla wczesnego wyjścia
fun process(data: String?): Result {
val safe = data ?: return Result.failure("No data")
return processInternal(safe)
}
Łączenie z let — częsty wzorzec w Kotlin, gdzie Elvis Operator ustawia wartość domyślną, a let wykonuje akcję z nie-null wynikiem. Takie podejście zastępuje całe bloki if-else jednym łańcuchem wywołań bez utraty czytelności. Elvis Operator może być również używany z throw do wymuszonego przerwania przy braku wymaganego parametru — to idiomatyczny sposób walidacji danych wejściowych.
W Kotlin rozpowszechniony jest wzorzec Elvis + return. Jeśli wartość jest null, funkcja natychmiast zwraca wynik lub zgłasza wyjątek. Idiom „Elvis with return” jest często używany w funkcjach transformacji danych: val processed = rawData ?: return defaultValue. Jest to bardziej zwięzłe niż guard let w Swift i nie zwiększa zagnieżdżenia kodu.
Elvis Operator jest krótszy niż if-else i nie wymaga powtarzania zmiennej. Porównaj: val x = a ?: b versus val x = if (a != null) a else b. Przy złożonych wyrażeniach redukcja kodu sięga 60%, przy czym semantyka jest całkowicie identyczna — kompilator może wygenerować ten sam kod bajtowy dla obu wariantów.
| Kryterium | Elvis Operator | if-else |
|---|---|---|
| Długość zapisu | 1 linia, 5–10 znaków | 3 linie, 15–30 znaków |
| Powtarzanie wyrażenia | Nie | Tak (a != null) ? a : b |
| Leniwy prawy operand | Tak | Tak (elvis krócej) |
| Efekty uboczne | Tylko w prawej części | W obu gałęziach |
| Czytelność | Wysoka dla prostych przypadków | Lepsza dla złożonej logiki |
Elvis Operator jest optymalny do przypisywania wartości domyślnej, wywoływania łańcuchów funkcji z bezpiecznym dostępem i logowania brakujących wartości. Idiomatyczne wzorce Kotlin zalecają go jako zamiennik if-else dla prostych null-sprawdzeń w wyrażeniach. W połączeniu z ?. daje zwarte łańcuchy bez zmiennych tymczasowych.
if-else pozostaje preferowany przy wielu warunkach, gdy trzeba wykonać efekty uboczne lub gdy oba operandy to złożone bloki kodu z wieloma operacjami. Elvis Operator nie obsługuje zagnieżdżonych bloków — tylko pojedyncze wyrażenia dla każdego operandu. Jeśli prawa część wywołuje funkcję z efektem ubocznym, czytelność if-else jest wyższa.
Groovy używa dokładnie tej samej składni ?: co Kotlin, ponieważ oba języki działają na JVM i dzielą filozofię null-safety. W Groovy operator pojawił się wcześniej — był w języku od wersji 1.8, wydanej w 2011 roku. Groovy obsługuje również Elvis-przypisanie: x ?= value (przypisz tylko jeśli x jest null).
def name = getUserName()
def display = name ?: "Guest"
def map = ["key": "value"]
def result = map?.get("missing") ?: "default"
println(result)
// Elvis-przypisanie w Groovy
def config = null
config ?= "defaultConfig"
assert config == "defaultConfig"
W Swift analog nazywa się nil-coalescing operator i zapisuje się jako ??. W Dart używana jest ta sama składnia ??. Różnica polega na tym, że Swift i Dart wymagają zgodności typów operandów, a Kotlin dopuszcza różne typy z automatycznym rzutowaniem do wspólnego supertypu. W TypeScript od wersji 3.7 pojawił się operator ?? (nullish coalescing), który działa tylko z null i undefined, w przeciwieństwie do ||, który filtruje wszystkie falsy-wartości. W PHP od wersji 7.0 pojawił się operator ??, w C# — ?? od wersji 6.0.
Najczęstszym błędem jest mylenie Elvis Operator ?: z operatorem bezpiecznego wywołania ?. W Kotlin ?. wywołuje metodę lub właściwość tylko jeśli obiekt nie jest null, a ?: zwraca wartość domyślną przy null. Łączy się je sekwencyjnie, ale każdy pełni swoją funkcję. Mylenie występuje u początkujących, którzy próbują używać ?: bez ?. przed nim.
Prawa część Elvis jest obliczana leniwie, ale jeśli znajduje się w niej wywołanie funkcji z efektami ubocznymi, może to prowadzić do nieoczekiwanego zachowania. Programiści czasami umieszczają w prawej części kosztowne obliczenia lub logowanie, które nie jest wykonywane przy nie-null wartości. Ważne jest, aby pamiętać, że prawa część to wyrażenie obliczane tylko w razie potrzeby.
Wiele Elvis po sobie może utrudniać czytanie kodu. Na przykład a ?: b ?: c ?: d jest wykonywane od lewej do prawej, zwracając pierwszy nie-null. Grupowanie przez nawiasy lub wydzielenie logiki do osobnej funkcji zwiększa czytelność i ułatwia debugowanie. Jeśli łańcuch jest dłuższy niż 3 elementy, warto użyć wyrażenia when lub funkcji pomocniczej.
Początkujący programiści czasami próbują używać Elvis Operator do sprawdzania wartości boolowskich: val x = flag ?: false. Działa to tylko wtedy, gdy flag może być null. Dla warunków boolowskich bez null potrzebny jest zwykły if-else lub operator trójargumentowy, którego w Kotlin nie ma, ale zastępuje go wyrażenie if-else: val x = if (flag) a else b.
Często zadawane pytania
Elvis Operator sprawdza tylko null, a operator trójargumentowy przyjmuje dowolny warunek boolowski. W Kotlin nie ma operatora trójargumentowego — zastępuje go wyrażenie if-else. Elvis rozwiązuje jedno konkretne zadanie: wartość domyślną przy null, podczas gdy operator trójargumentowy obejmuje wszystkie wyrażenia warunkowe.
Tak, w prawej części może być wywołanie funkcji: val x = a ?: calculateDefault(). Funkcja jest obliczana tylko przy null wartości a dzięki leniwemu obliczaniu. Pozwala to na używanie kosztownych obliczeń, wywołań API lub zapytań do bazy danych bez utraty wydajności przy istniejącej wartości.
W Java nie ma bezpośredniego Elvis Operator. Od Java 8 można użyć Optional.ofNullable(value).orElse(default). W Java 14+ pojawiły się wyrażenia switch, ale pełnowartościowy ?: nie istnieje. Kotlin i Groovy udostępniają go jako wbudowaną konstrukcję składniową języka.
Typowy wzorzec: safe call ?. następnie Elvis. Przykład: user?.address?.city ?: "Unknown". Jeśli którykolwiek element łańcucha jest null — zwracana jest wartość domyślna. To zwarta zamiana zagnieżdżonych if-sprawdzeń, która skraca kod 3–5 razy w porównaniu z tradycyjnym podejściem.
Elvis Operator to konstrukcja składniowa na poziomie języka, orElse to metoda Optional w Java. Elvis jest wykonywany leniwie (prawa część obliczana tylko przy null), orElse zawsze oblicza argument. Dla leniwego wariantu w Java istnieje orElseGet, przyjmujący Supplier. Elvis jest krótszy i nie wymaga tworzenia Optional.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również