Operador Elvis em Kotlin: ?: não funciona como você pensava

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Operador Elvis em Kotlin: não é apenas "se for null, então…"

\n\n

Se você já escreveu em Kotlin e lidou com null, com certeza já viu este emoticon engraçado com cabelo — o operador ?:. Ele é chamado de Operador Elvis, e na comunidade Kotlin se tornou um verdadeiro meme. Mas por trás dessa sintaxe simples, esconde-se uma mecânica surpreendentemente complexa e interessante.

\n\n

Hoje vamos analisar o operador Elvis em Kotlin não como mais um "açúcar sintático", mas como uma ferramenta poderosa que, no nível do bytecode, resolve o problema de null-safety. Você descobrirá o que acontece quando o compilador encontra ?: e por que em alguns casos ele é mais rápido que if-else.

\n\n

O artigo é baseado em uma pergunta real do Stack Overflow com milhares de visualizações — adaptamos para um conteúdo educacional profundo. Vamos nessa!

\n\n

O que é o Operador Elvis e com o que se come

\n\n

Formalmente, o Operador Elvis é um operador binário que retorna o operando esquerdo se ele não for null, e o direito caso contrário. Sintaxe:

\n\n
val result = nullableValue ?: defaultValue
\n\n

O nome vem da semelhança com o penteado de Elvis Presley, se você virar a cabeça de lado: ?: são os olhos e o topete. Engraçado, mas no mundo da programação esse nome pegou.

\n\n

Em Kotlin, este operador faz parte do sistema de null safety. Ele permite escrever código conciso sem verificações extensas:

\n\n
// Em vez disso:\nval length: Int\nif (str != null) {\n    length = str.length\n} else {\n    length = 0\n}\n\n// Escrevemos assim:\nval length = str?.length ?: 0
\n\n

A pegadinha que os tutoriais omitem

\n\n

Muitos pensam que ?: é apenas uma forma abreviada de if-else. Mas não é bem assim. O compilador Kotlin gera bytecode diferente para essas duas construções. E a diferença pode afetar o desempenho e o comportamento do programa.

\n\n

Como ?: funciona por baixo dos panos: bytecode e JVM

\n\n

Vamos dar uma olhada nos bastidores. Pegue um exemplo simples e veja no que o compilador Kotlin o transforma para a JVM.

\n\n

Código fonte em Kotlin

\n\n
fun getLength(str: String?): Int {\n    return str?.length ?: 0\n}
\n\n

Código Java descompilado (aproximadamente)

\n\n
public static final int getLength(@Nullable String str) {\n    Integer var10000 = str != null ? str.length() : null;\n    return var10000 != null ? var10000 : 0;\n}
\n\n

Viu? O compilador não substitui simplesmente ?: por if-else. Ele cria uma variável temporária do tipo Integer? (boxing!) e depois aplica um segundo ?:. Isso é chamado de dupla verificação.

\n\n

Por que isso acontece?

\n\n

Porque str?.length retorna Int? (nullable Int). E ?: espera que o operando esquerdo possa ser null. O compilador não pode "unir" essas duas verificações em uma — ele precisa preservar a semântica da chamada segura.

\n\n

Como resultado, se str não for null, são executadas duas verificações de null em vez de uma. Para a maioria das aplicações, isso é imperceptível, mas em loops de alta carga pode se tornar um gargalo.

\n\n

Otimização: quando o Operador Elvis é mais rápido que if-else

\n\n

Mas há uma boa notícia. Em alguns casos, o Operador Elvis gera um bytecode mais eficiente do que a verificação manual.

\n\n

Considere um exemplo com retorno antecipado:

\n\n
// Com if-else\nfun process(value: String?): String {\n    if (value == null) return "default"\n    return value.uppercase()\n}\n\n// Com Elvis\nfun process(value: String?): String {                

Blogs

Book Recommendations