Nullable em Kotlin: como trabalhar com valores null sem dor? Guia completo

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

O que está escondido atrás do ponto de interrogação? Mergulhando no nullable em Kotlin

\n\n

Você já escreveu em Java e pegou um NullPointerException no pior momento possível? Se sim — você sabe como isso dói. Os desenvolvedores do Kotlin resolveram esse problema de uma vez por todas, tornando a null safety não apenas um recurso, mas uma filosofia da linguagem. Mas os iniciantes frequentemente se assustam com a pergunta: "In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them?" (é assim que soa a pergunta mais popular no Stack Overflow).

\n\n

Hoje vamos analisar todas as expressões idiomáticas para trabalhar com nullable: desde o simples ?. até o astuto let e o mágico !!. E o mais importante — vamos olhar por baixo dos panos para entender como isso funciona no nível do bytecode. Vamos nessa!

\n\n

Breve introdução: o que é nullable?

\n\n

Em Kotlin, os tipos são divididos em dois grupos: nullable (podem ser null) e non-nullable (não podem). Se você escrever var name: String = null — o compilador dará erro. Já var name: String? = null — ok. O ponto de interrogação é um marcador que diz: "Ei, compilador, eu sei que aqui pode estar vazio, não reclame".

\n\n

Mas como trabalhar com isso? Simplesmente verificar se é null com if — é chato e não é o estilo Kotlin. Vamos ver as ferramentas reais.

\n\n

A trindade salvadora: ?, ?: e ?.

\n\n

Kotlin oferece três pilares que sustentam todo o trabalho com nullable. Lembre-se deles — eles vão economizar horas de depuração.

\n\n

1. Safe call operator (?.)

\n\n

Este é o convidado mais frequente no seu código. O operador safe call permite chamar um método ou propriedade apenas se o objeto não for null. Se o objeto for null — o operador retorna null, e nenhuma exceção.

\n\n
val user: User? = null\nval name: String? = user?.name  // name = null, nenhum erro
\n\n

Por baixo dos panos, isso se transforma em bytecode que faz uma verificação comum de null e uma chamada condicional. Nenhuma mágica, apenas segurança.

\n\n

2. Elvis operator (?:)

\n\n

Elvis é seu amigo quando você precisa definir um valor padrão. Se a parte esquerda não for null — pegamos ela, caso contrário — o que está à direita.

\n\n
val name: String? = null\nval displayName: String = name ?: "Convidado"  // "Convidado"
\n\n

Elvis também pode ser usado para saída antecipada de uma função:

\n\n
fun getUserName(user: User?): String {\n    val name = user?.name ?: return "Anônimo"\n    return name\n}
\n\n

3. Not-null assertion (!!)

\n\n

Este é o operador rebelde. Ele diz: "Tenho certeza que aqui não é null, e estou pronto para morrer (no sentido de lançar um NPE) se estiver errado". Use com cuidado, apenas quando tiver 100% de certeza.

\n\n
val user: User? = getUserFromDatabase() // temos certeza que ele existe\nval name: String = user!!.name
\n\n

Por baixo dos panos, !! é compilado em uma verificação comum com lançamento de NullPointerException se for null. Nada complicado, mas perigoso.

\n\n

Forma idiomática: let, run, apply e companhia

\n\n

Agora vamos ao mais interessante. A pergunta no Stack Overflow é exatamente sobre isso: como transformar valores nullable de forma idiomática. A resposta — funções de extensão da biblioteca padrão.

\n\n

let — o rei das transformações nullable

\n\n

A função let executa um bloco de código apenas se o objeto não for null. Dentro do bloco, o objeto está disponível como it (ou pode ser renomeado).

\n\n
val user: User? = getUser()\nuser?.let { \n    println("Nome do usuário: ${it.name}")\n    // Aqui it — garantidamente não é null\n}
\n\n

Esta é a forma idiomática de executar uma ação apenas quando o valor não é null. Sem o let, teria que escrever:

\n\n
if (user != null) {\n    println("Nome do usuário: ${user.name}")\n}

Blogs

Book Recommendations