O que é when em Kotlin?
O when é a versão turbinada do switch em Kotlin. Ele funciona tanto como expressão (retorna valor) quanto como instrução (executa blocos). É mais poderoso e flexível que o switch de Java ou C — suporta ranges, verificações de tipo, condições complexas é muito mais.
Sintaxe básica
fun classificarNota(nota: Int): String {
return when (nota) {
10 -> "Perfeito!"
in 7..9 -> "Aprovado"
in 5..6 -> "Recuperação"
in 0..4 -> "Reprovado"
else -> "Nota invalida"
}
}
fun main() {
println(classificarNota(8)) // Aprovado
println(classificarNota(3)) // Reprovado
}
When como expressão
Quando when é usado como expressão (retornando valor), o else é obrigatório — a menos que o compilador consiga verificar que todos os casos estão cobertos:
enum class DiaSemana { SEG, TER, QUA, QUI, SEX, SAB, DOM }
fun tipoDeDia(dia: DiaSemana) = when (dia) {
DiaSemana.SEG, DiaSemana.TER, DiaSemana.QUA,
DiaSemana.QUI, DiaSemana.SEX -> "Dia util"
DiaSemana.SAB, DiaSemana.DOM -> "Fim de semana"
}
Verificação de tipo com is
fun descrever(obj: Any): String = when (obj) {
is String -> "Texto com ${obj.length} caracteres"
is Int -> "Número inteiro: $obj"
is List<*> -> "Lista com ${obj.size} itens"
is Boolean -> if (obj) "Verdadeiro" else "Falso"
else -> "Tipo desconhecido"
}
fun main() {
println(descrever("Kotlin")) // Texto com 6 caracteres
println(descrever(42)) // Número inteiro: 42
println(descrever(listOf(1, 2, 3))) // Lista com 3 itens
}
Repare que dentro de cada branch, o smart cast já aplica o tipo automaticamente.
When sem argumento
Você pode usar when sem argumento, funcionando como uma cadeia de if-else:
fun avaliarTemperatura(temp: Double): String = when {
temp < 0 -> "Congelante!"
temp < 15 -> "Tá frio, hein"
temp < 25 -> "Temperatura agradável"
temp < 35 -> "Tá quente"
else -> "Derretendo!"
}
fun main() {
println(avaliarTemperatura(28.0)) // Tá quente
}
When com sealed class
A combinação com sealed class é perfeita — o compilador garante que todos os casos são tratados, sem precisar de else. Essa é uma das duplas mais poderosas do Kotlin pra modelar estados e resultados.
sealed class Resultado {
data class Sucesso(val dados: String) : Resultado()
data class Erro(val mensagem: String) : Resultado()
data object Carregando : Resultado()
}
fun tratarResultado(resultado: Resultado): String = when (resultado) {
is Resultado.Sucesso -> "Dados recebidos: ${resultado.dados}"
is Resultado.Erro -> "Falha: ${resultado.mensagem}"
is Resultado.Carregando -> "Aguarde, carregando..."
}
fun main() {
val r1 = Resultado.Sucesso("Lista de usuários")
val r2 = Resultado.Erro("Timeout na conexão")
val r3 = Resultado.Carregando
println(tratarResultado(r1)) // Dados recebidos: Lista de usuários
println(tratarResultado(r2)) // Falha: Timeout na conexão
println(tratarResultado(r3)) // Aguarde, carregando...
}
Como Resultado é uma sealed class, o compilador sabe que existem exatamente três subtipos. Se você adicionar um novo subtipo no futuro, o compilador vai avisar em todos os when que ficaram incompletos.
When com múltiplas condições e guardas
A partir do Kotlin 1.9, o when ganhou suporte a guard conditions, que permitem adicionar condições extras a cada branch usando if.
fun classificarIdade(idade: Int, temDocumento: Boolean): String = when {
idade < 0 -> "Idade invalida"
idade < 12 -> "Criança"
idade < 18 && temDocumento -> "Adolescente com documento"
idade < 18 -> "Adolescente sem documento"
idade < 60 -> "Adulto"
else -> "Idoso"
}
fun main() {
println(classificarIdade(15, true)) // Adolescente com documento
println(classificarIdade(15, false)) // Adolescente sem documento
println(classificarIdade(45, true)) // Adulto
}
Casos de Uso no Mundo Real
- Tratamento de respostas HTTP: O
whené ideal para tratar diferentes códigos de status HTTP. Você pode agrupar ranges comoin 200..299para sucesso,in 400..499para erros do cliente ein 500..599para erros do servidor, tornando o código muito mais legível do que uma cadeia deif-else. - Navegação em aplicativos Android: Em apps com Jetpack Compose ou Fragments, o
whencombinado com sealed classes é o padrão para decidir qual tela exibir com base no estado atual de navegação. - Parsing de formatos de dados: Ao processar dados de diferentes formatos (JSON, XML, CSV), o
whencom verificação de tipo (is) permite tratar cada formato de maneira específica com smart cast automático. - Máquinas de estado: Sistemas como processamento de pedidos (novo, pago, enviado, entregue, cancelado) se beneficiam enormemente do
whencom sealed classes, garantindo que toda transição de estado é tratada explicitamente.
Boas Práticas
- Prefira
whencomo expressão: Sempre que possível, usewhenretornando um valor diretamente comval resultado = when { ... }. Isso elimina a necessidade de variáveis mutáveis e torna o código mais funcional. - Use sealed classes em vez de
else: Quando você tem um conjunto fixo de tipos ou estados, modele-os com sealed classes. O compilador vai garantir que todos os casos sejam tratados, e qualquer novo caso adicionado no futuro será detectado em tempo de compilação. - Agrupe valores relacionados: O
whenpermite agrupar múltiplos valores na mesma branch usando vírgula, como'a', 'e', 'i', 'o', 'u' -> "vogal". Use isso para evitar duplicação de lógica. - Prefira
whena cadeias longas deif-else: Quando você tem três ou mais condições sobre o mesmo valor,whené quase sempre mais legível e menos propenso a erros do queif-else if-else. - Aproveite o smart cast: Dentro de branches com
is, o Kotlin já faz o cast automaticamente. Não useasmanualmente após verificar o tipo comis— isso é redundante e polui o código.
Erros Comuns
- Esquecer o
elseem expressõeswhen: Quandowhené usado como expressão (retornando valor), oelseé obrigatório se os casos não são exaustivos. O compilador vai apontar o erro, mas é comum esquecer durante a escrita inicial. - Ordem errada dos branches: O
whenavalia os branches de cima para baixo e executa o primeiro que corresponder. Se você colocar um branch mais genérico antes de um mais específico, o específico nunca será alcançado. Por exemplo,is Numberantes deis Intfaz com que inteiros caiam sempre no branch deNumber. - Não aproveitar ranges: Escrever
1 -> ..., 2 -> ..., 3 -> ...quando todos retornam o mesmo valor é desnecessário. Usein 1..3 -> ...para simplificar. O mesmo vale para verificações como"a", "b", "c" -> .... - Usar
whenpara apenas dois casos: Se você tem apenas duas opções (verdadeiro/falso, presente/ausente), um simplesif-elseé mais claro e conciso do que umwhen. Usewhenquando há três ou mais caminhos. - Não tratar todos os casos de um enum: Mesmo quando o
whené usado como instrução (sem retornar valor), é boa prática tratar todos os valores do enum. Isso evita bugs silenciosos quando novos valores são adicionados ao enum no futuro.
Perguntas Frequentes
when substitui completamente o switch do Java? Sim, e vai muito além. O when do Kotlin suporta verificação de tipo com is, ranges com in, condições arbitrárias (quando usado sem argumento), e funciona como expressão. O switch do Java é limitado a valores constantes de tipos primitivos, enums e strings.
Posso usar when sem chaves nas branches? Sim. Se a branch tem apenas uma expressão, não precisa de chaves: 10 -> "dez". Mas se precisa de múltiplas instruções, envolva com chaves e a última expressão será o valor de retorno da branch.
O when é mais performático que if-else? Depende do caso. Para comparações com valores constantes de Int ou String, o compilador pode gerar um tableswitch ou lookupswitch no bytecode, que é mais eficiente que uma série de comparações. Para condições complexas ou when sem argumento, a performance é equivalente a if-else.
Como funciona o when com valor de retorno em blocos? Quando uma branch do when usa chaves para múltiplas instruções, a última expressão do bloco é o valor retornado. Por exemplo: in 1..10 -> { println("Processando"); "válido" } retorna "válido".
Termos Relacionados
- Sealed Class — Classes seladas que combinam perfeitamente com
whenpara garantir exaustividade. - Enum — Enumerações que permitem
whenexaustivo semelse. - val — Variáveis somente leitura, ideais para receber o resultado de uma expressão
when. - Smart Cast — O mecanismo que permite usar o tipo verificado com
isdentro das branches dowhen.