0Pricing
Kotlin Academy · Aula

Relançamento e encadeamento de exceções

Relance exceções seletivamente e envolva erros de baixo nível, encadeando suas causas.

Relançamento e encadeamento de exceções é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.

Relançando e encapsulando

Às vezes, você captura uma exceção apenas para fazer log, encapsulá-la ou convertê-la antes de permitir que uma exceção mais específica se propague. O Kotlin torna isso idiomático.

Relançamento simples

Para relançar, basta usar throw e novamente — a propagação continua até o próximo manipulador.

fun main() {
    try {
        try { "x".toInt() }
        catch (e: NumberFormatException) {
            println("logging: ${e.message}")
            throw e // re-throw original
        }
    } catch (e: NumberFormatException) {
        println("outer caught: ${e.message}")
    }
}

Encapsulamento com uma exceção personalizada

Passe a exceção original como cause ao construir uma nova, para preservar a cadeia.

class ParseException(msg: String, cause: Throwable) : RuntimeException(msg, cause)
fun main() {
    try {
        try { "xyz".toInt() }
        catch (e: NumberFormatException) {
            throw ParseException("could not parse user input", e)
        }
    } catch (e: ParseException) {
        println("got: ${e.message}")
        println("cause: ${e.cause?.message}")
    }
}

Inspecionando a cadeia de causas

A propriedade cause aponta para a exceção anterior. Percorra-a para imprimir a causa raiz completa.

fun main() {
    val e = RuntimeException("top",
        RuntimeException("middle",
            RuntimeException("root")))
    var current: Throwable? = e
    while (current != null) {
        println(current.message)
        current = current.cause
    }
}

Relançamento seletivo

Capture um tipo amplo e depois relance-o se NOT corresponder ao caso esperado.

fun parseRequired(s: String): Int {
    try {
        return s.toInt()
    } catch (e: NumberFormatException) {
        if (s.isBlank()) return 0
        throw e // unexpected — let it propagate
    }
}
fun main() {
    println(parseRequired("42"))
    println(parseRequired(""))
    // parseRequired("abc") // throws
}

Adicionando contexto

Encapsule com uma exceção de domínio para adicionar o contexto que faltava à original — entrada, identificador da requisição etc.

class UploadError(msg: String, cause: Throwable) : RuntimeException(msg, cause)
fun upload(file: String) {
    try { throw RuntimeException("disk full") }
    catch (e: Throwable) { throw UploadError("uploading $file failed", e) }
}
fun main() {
    try { upload("photo.jpg") }
    catch (e: UploadError) { println("${e.message} <- ${e.cause?.message}") }
}

Não perca o rastreamento da pilha

Ao encapsular, sempre passe a exceção original como cause — nunca crie apenas uma nova exceção com a mesma mensagem, mas sem causa. O rastreamento da pilha é seu recurso essencial para depuração.

class Wrapped(m: String, cause: Throwable) : RuntimeException(m, cause)
fun main() {
    try {
        try { error("inner") }
        catch (e: Throwable) { throw Wrapped("outer", e) }
    } catch (e: Wrapped) {
        println("message: ${e.message}")
        println("cause: ${e.cause?.message}")
    }
}

Relance sem encapsular

Se tudo de que precisa é fazer log, basta usar throw e depois da chamada de log — não é necessário encapsular.

fun risky() {
    try { throw IllegalStateException("oops") }
    catch (e: IllegalStateException) {
        println("Logging before rethrow: ${e.message}")
        throw e
    }
}
fun main() {
    try { risky() }
    catch (e: IllegalStateException) { println("outer: ${e.message}") }
}

finally para limpeza durante o relançamento

Use finally para limpar os recursos mesmo ao relançar uma exceção.

fun process() {
    try {
        throw RuntimeException("failure")
    } finally {
        println("cleanup ran")
    }
}
fun main() {
    try { process() }
    catch (e: RuntimeException) { println("caught: ${e.message}") }
}

Exceções suprimidas

Se o próprio finally lançar uma exceção, a exceção original será suprimida por padrão. Use addSuppressed para preservar ambas.

fun main() {
    val primary = RuntimeException("primary")
    val secondary = RuntimeException("from cleanup")
    primary.addSuppressed(secondary)
    println(primary.suppressed.joinToString { it.message ?: "?" })
}

Antipadrão: engolir e depois lançar uma diferente

Capturar uma exceção e lançar outra, sem relação com ela e sem causa, destrói informações importantes para a depuração. Sempre informe cause.

// BAD
// catch (e: IOException) { throw RuntimeException("error") }
// GOOD
// catch (e: IOException) { throw RuntimeException("error reading config", e) }
fun main() { println("Pass cause when re-throwing!") }

Verificação rápida

Ao encapsular uma exceção em uma nova, o que deve fazer para preservar o rastreamento de pilha original?

Recapitulação

Para lançar novamente: throw e. Para encapsular: lance uma nova exceção com cause = e. Preserve sempre a cadeia de causas — nunca crie um encapsulador sem causa. Use finally para a limpeza e addSuppressed quando a própria limpeza falhar.

Perguntas Frequentes

A aula “Relançamento e encadeamento de exceções” é grátis?

Sim — o texto completo de “Relançamento e encadeamento de exceções” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.

O que vou aprender em “Relançamento e encadeamento de exceções”?

Relance exceções seletivamente e envolva erros de baixo nível, encadeando suas causas. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Kotlin Academy?

Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Relançamento e encadeamento de exceções”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Kotlin Academy?

Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. try/catch/finally como expressão
  2. Criando classes de exceção personalizadas
  3. runCatching e Result
  4. Relançamento e encadeamento de exceções
← Voltar para Kotlin Academy