---
title: "When em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/when/"
markdown_url: "https://kotlin.dev.br/glossario/when.MD"
description: "Entenda o que é when em Kotlin, como usar essa expressão poderosa que substitui o switch-case de outras linguagens."
date: "2026-02-16"
author: "Karina Melo"
---

# When em Kotlin: O que É e Como Funciona | Kotlin Brasil

Entenda o que é when em Kotlin, como usar essa expressão poderosa que substitui o switch-case de outras linguagens.


## 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

```kotlin
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:

```kotlin
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`

```kotlin
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`:

```kotlin
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.

```kotlin
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`.

```kotlin
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 como `in 200..299` para sucesso, `in 400..499` para erros do cliente e `in 500..599` para erros do servidor, tornando o código muito mais legível do que uma cadeia de `if-else`.
- **Navegação em aplicativos Android**: Em apps com Jetpack Compose ou Fragments, o `when` combinado 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 `when` com 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 `when` com sealed classes, garantindo que toda transição de estado é tratada explicitamente.

### Boas Práticas

- **Prefira `when` como expressão**: Sempre que possível, use `when` retornando um valor diretamente com `val 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 `when` permite 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 `when` a cadeias longas de `if-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 que `if-else if-else`.
- **Aproveite o smart cast**: Dentro de branches com `is`, o Kotlin já faz o cast automaticamente. Não use `as` manualmente após verificar o tipo com `is` — isso é redundante e polui o código.

### Erros Comuns

- **Esquecer o `else` em expressões `when`**: Quando `when` é usado como expressão (retornando valor), o `else` é 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 `when` avalia 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 Number` antes de `is Int` faz com que inteiros caiam sempre no branch de `Number`.
- **Não aproveitar ranges**: Escrever `1 -> ..., 2 -> ..., 3 -> ...` quando todos retornam o mesmo valor é desnecessário. Use `in 1..3 -> ...` para simplificar. O mesmo vale para verificações como `"a", "b", "c" -> ...`.
- **Usar `when` para apenas dois casos**: Se você tem apenas duas opções (verdadeiro/falso, presente/ausente), um simples `if-else` é mais claro e conciso do que um `when`. Use `when` quando 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](/glossario/sealed-class) — Classes seladas que combinam perfeitamente com `when` para garantir exaustividade.
- [Enum](/glossario/enum) — Enumerações que permitem `when` exaustivo sem `else`.
- [val](/glossario/val) — Variáveis somente leitura, ideais para receber o resultado de uma expressão `when`.
- [Smart Cast](/glossario/smart-cast) — O mecanismo que permite usar o tipo verificado com `is` dentro das branches do `when`.
