Introdução: Adeus, switch-case? Bem-vindo, when!
Se você veio para Kotlin vindo do mundo Java, C# ou JavaScript, a primeira coisa que provavelmente procura é o familiar operador switch-case. E aí vem a surpresa: em Kotlin não existe switch-case clássico. Em vez disso, a linguagem oferece uma ferramenta muito mais poderosa e flexível — when.
No Stack Overflow, a pergunta "How to implement switch-case statement in Kotlin" acumula milhares de visualizações. É normal: desenvolvedores se acostumam com certas construções e querem encontrar análogas. Mas a verdade é que when em Kotlin não é apenas uma substituição para switch. É sua evolução, que por baixo dos panos funciona de forma mais inteligente e rápida.
Neste artigo, não vamos apenas mostrar como escrever when. Vamos olhar por baixo dos panos: descobrir em que seu código é compilado, por que ele é mais rápido que switch em alguns cenários e como usar when ao máximo.
1. Sintaxe básica: de switch-case para when
Para começar — o exemplo mais simples. Vamos imaginar que temos a velha e boa construção Java:
// Javaint day = 3;String dayName;switch (day) { case 1: dayName = "Segunda-feira"; break; case 2: dayName = "Terça-feira"; break; case 3: dayName = "Quarta-feira"; break; default: dayName = "Dia desconhecido";}Em Kotlin, ficaria assim:
// Kotlinval day = 3val dayName = when (day) { 1 -> "Segunda-feira" 2 -> "Terça-feira" 3 -> "Quarta-feira" else -> "Dia desconhecido"}Já aqui vemos duas principais vantagens:
- Sem break — Kotlin sai automaticamente do bloco após executar o ramo.
- Retorna valor — pode-se atribuir o resultado a uma variável.
2. Como o when funciona por baixo dos panos: bytecode e otimização
Agora a parte mais interessante. Quando você escreve when, o compilador Kotlin analisa suas condições e escolhe a forma ideal de execução. Vamos dar uma olhada no bytecode (aproximadamente, sem detalhes desnecessários).
Caso 1: when com constantes (como switch-case)
Se você usa when com números inteiros, strings ou constantes enum, o compilador gera uma tabela de transição (tableswitch ou lookupswitch). É o mesmo mecanismo que Java usa para switch-case. A diferença é que Kotlin faz isso automaticamente, sem sua intervenção.
Caso 2: when com quaisquer condições
Se você escreve algo como:
when (x) { in 1..10 -> "Pequeno" in 11..100 -> "Médio" else -> "Grande"}O compilador não pode usar a tabela de transição. Ele gera uma cadeia de if-else. Mas Kotlin faz isso da forma mais eficiente possível: as condições são verificadas em ordem e, assim que uma correspondência é encontrada, a execução é interrompida.
Caso 3: when sem argumento
Isso é uma mágica à parte. Se você escreve:
when { x > 0 -> "Positivo" x < 0 -> "Negativo" else -> "Zero"}O compilador transforma isso em if-else comuns. Mas a sintaxe é muito mais limpa do que ifs aninhados.
Conclusão: Kotlin não apenas copia o switch-case. Ele escolhe inteligentemente entre tabela de transição e if-else para que seu código funcione o mais rápido possível.
3. Recursos avançados do when: o que não existe no switch
when é capaz de muito mais do que apenas comparar valores. Aqui estão alguns recursos matadores:
3.1. Verificação de tipos (smart cast)
fun describe(obj: Any): String = when (obj) { is String -> "String de comprimento ${obj.length}" // smart cast para String is Int -> "Número inteiro" is List<*> -> "Lista com ${obj.size} elementos" else -> "Tipo desconhecido"}