Elvis Operator — je binární operátor, který vrací levý operand, pokud není null, a pravý v opačném případě. Zapisuje se jako ?: v Kotlin, Groovy a některých dalších jazycích. Podle Kotlin Language Documentation, 2024 je operátor součástí systému null-bezpečnosti jazyka a umožňuje zkrátit podmíněné konstrukce na jeden řádek bez ztráty čitelnosti. Na rozdíl od úplného zápisu if-else, Elvis Operator vypočítává pravou část pouze při null hodnotě levé, což poskytuje výhodu v výkonu při použití drahých výchozích výrazů.
Hlavní body
Elvis Operator — binární operátor pojmenovaný podle účesu Elvise Presleyho. Symbol ?: vizuálně připomíná tvář zpěváka z profilu: otazník — oko a licousy, dvojtečka — ústa. Operátor přijímá dva operandy: pokud první není null — vrátí se on, jinak se vrátí druhý. To umožňuje nahradit úplnou konstrukci if-else jedním krátkým zápisem.
Název „Elvis Operator“ se ujal v komunitě Kotlin a Groovy a poté přešel do Xtend a dalších JVM jazyků. V Swift a Dart se podobná konstrukce nazývá nil-coalescing operator, ale je funkčně identická. Vizuální asociace s Elvisem Presleym pomohla operátoru stát se jedním z nejznámějších symbolů v syntaxi moderních programovacích jazyků.
Elvis Operator je součástí systému null safety, který zabraňuje NullPointerException (NPE). Podle výzkumu JetBrains z roku 2023 tvoří NPE 28% všech výjimek v produkčním kódu na JVM. Použití Elvis Operator zcela eliminuje NPE v místě přiřazení a zaručuje výchozí hodnotu. V kombinaci s operátorem bezpečného volání ?. vzniká spolehlivý řetězec bez jediného bloku if.
V Kotlin se Elvis Operator zapisuje jako ?: mezi dvěma výrazy. Pokud levý výraz není null — výsledek se rovná levému, jinak se vypočítá pravý. Pravý výraz se vypočítává líně — pouze když je levý operand null, což je důležité pro výkon při použití drahých výpočtů nebo volání 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("Časový limit: $timeout")
// Elvis s throw pro povinné parametry
val requiredId = nullableId ?: throw IllegalArgumentException("ID is required")
// Elvis s return pro předčasné ukončení
fun process(data: String?): Result {
val safe = data ?: return Result.failure("No data")
return processInternal(safe)
}
Kombinace s let — častý vzor v Kotlin, kde Elvis Operator nastaví výchozí hodnotu a let provede akci s ne-null výsledkem. Tento přístup nahrazuje celé bloky if-else jedním řetězcem volání bez ztráty čitelnosti. Elvis Operator lze také použít s throw pro vynucené přerušení při chybějícím povinném parametru — to je idiomatický způsob validace vstupních dat.
V Kotlin je rozšířený vzor Elvis + return. Pokud je hodnota null, funkce okamžitě vrátí výsledek nebo vyvolá výjimku. Idiom „Elvis with return“ se často používá v funkcích transformace dat: val processed = rawData ?: return defaultValue. Je kompaktnější než guard let v Swift a nezvyšuje vnoření kódu.
Elvis Operator je kratší než if-else a nevyžaduje opakování proměnné. Porovnejte: val x = a ?: b versus val x = if (a != null) a else b. U složitých výrazů dosahuje redukce kódu 60%, přičemž sémantika je zcela identická — kompilátor může vygenerovat stejný byte-code pro obě varianty.
| Kritérium | Elvis Operator | if-else |
|---|---|---|
| Délka zápisu | 1 řádek, 5–10 znaků | 3 řádky, 15–30 znaků |
| Opakování výrazu | Ne | Ano (a != null) ? a : b |
| Líná pravá strana | Ano | Ano (elvis kratší) |
| Vedlejší účinky | Pouze na pravé straně | V obou větvích |
| Čitelnost | Vysoká pro jednoduché případy | Lepší pro složitou logiku |
Elvis Operator je optimální pro přiřazení výchozí hodnoty, volání řetězců funkcí s bezpečným přístupem a logování chybějících hodnot. Idiomatické vzory Kotlin jej doporučují jako náhradu if-else pro jednoduché null kontroly ve výrazech. V kombinaci s ?. poskytuje kompaktní řetězce bez dočasných proměnných.
if-else zůstává vhodnější při více podmínkách, když je třeba provést vedlejší účinky nebo když jsou oba operandy složité bloky kódu s více operacemi. Elvis Operator nepodporuje vnořené bloky — pouze jednoduché výrazy pro každý operand. Pokud pravá strana volá funkci s vedlejším účinkem, čitelnost if-else je vyšší.
Groovy používá přesně stejnou syntaxi ?: jako Kotlin, protože oba jazyky běží na JVM a sdílejí filozofii null-safety. V Groovy se operátor objevil dříve — byl v jazyce od verze 1.8, vydané v roce 2011. Groovy také podporuje Elvis přiřazení: x ?= value (přiřadit pouze pokud je x null).
def name = getUserName()
def display = name ?: "Guest"
def map = ["key": "value"]
def result = map?.get("missing") ?: "default"
println(result)
// Elvis přiřazení v Groovy
def config = null
config ?= "defaultConfig"
assert config == "defaultConfig"
V Swift se analog nazývá nil-coalescing operator a zapisuje se jako ??. V Dart se používá stejná syntaxe ??. Rozdíl je v tom, že Swift a Dart vyžadují shodu typů operandů, zatímco Kotlin umožňuje různé typy s automatickou konverzí na společný supertyp. V TypeScript se od verze 3.7 objevil operátor ?? (nullish coalescing), který pracuje pouze s null a undefined, na rozdíl od ||, který filtruje všechny falsy hodnoty. V PHP se od verze 7.0 objevil operátor ??, v C# — ?? od verze 6.0.
Nejčastější chyba — zaměňování Elvis Operator ?: s operátorem bezpečného volání ?. V Kotlin ?. volá metodu nebo vlastnost pouze pokud objekt není null, a ?: vrací výchozí hodnotu při null. Kombinují se sekvenčně, ale každý plní svou funkci. Záměna vzniká u začátečníků, kteří se snaží použít ?: bez ?. před ním.
Pravá část Elvis se vypočítává líně, ale pokud se v ní nachází volání funkce s vedlejšími účinky, může to vést k neočekávanému chování. Vývojáři někdy umísťují do pravé části drahé výpočty nebo logování, které se neprovede při ne-null hodnotě. Je důležité si pamatovat, že pravá část je výraz, který se vypočítává pouze v případě potřeby.
Více Elvis za sebou může ztížit čtení kódu. Například a ?: b ?: c ?: d se provádí zleva doprava a vrací první ne-null. Seskupení pomocí závorek nebo vyjmutí logiky do samostatné funkce zvyšuje čitelnost a usnadňuje ladění. Pokud je řetězec delší než 3 prvky, vyplatí se použít when výraz nebo pomocnou funkci.
Začínající vývojáři se někdy snaží použít Elvis Operator pro kontrolu booleovských hodnot: val x = flag ?: false. To funguje pouze pokud flag může být null. Pro booleovské podmínky bez null je potřeba běžný if-else nebo ternární operátor, který v Kotlin neexistuje, ale je nahrazen výrazem if-else: val x = if (flag) a else b.
Často kladené otázky
Elvis Operator kontroluje pouze null, zatímco ternární operátor přijímá jakoukoli booleovskou podmínku. V Kotlin není ternární operátor — nahrazuje ho výraz if-else. Elvis řeší jeden konkrétní úkol: výchozí hodnotu při null, zatímco ternární operátor pokrývá všechny podmíněné výrazy.
Ano, na pravé straně může být volání funkce: val x = a ?: calculateDefault(). Funkce se vypočítá pouze když je hodnota a null díky línému vyhodnocování. To umožňuje používat drahé výpočty, volání API nebo databázové dotazy bez ztráty výkonu, když hodnota existuje.
V Java neexistuje přímý Elvis Operator. Od Java 8 lze použít Optional.ofNullable(value).orElse(default). V Java 14+ se objevily switch výrazy, ale plnohodnotný ?: chybí. Kotlin a Groovy jej poskytují jako vestavěnou syntaktickou konstrukci jazyka.
Typický vzor: safe call ?. poté Elvis. Příklad: user?.address?.city ?: "Unknown". Pokud je jakýkoli prvek řetězce null — vrátí se výchozí hodnota. To je kompaktní náhrada vnořených if kontrol, která zkracuje kód 3–5krát ve srovnání s tradičním přístupem.
Elvis Operator je syntaktická konstrukce na úrovni jazyka, orElse je metoda Optional v Java. Elvis se provádí líně (pravá část se vypočítává pouze při null), orElse vždy vypočítává argument. Pro línou variantu v Java existuje orElseGet, který přijímá Supplier. Elvis je kratší a nevyžaduje vytváření Optional.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také