Rilanciare eccezioni e concatenarle
Rilanci selettivamente le eccezioni e racchiuda gli errori di livello inferiore mantenendo la catena delle cause.
Rilanciare eccezioni e concatenarle è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.
Rilancio e wrapping
A volte si intercetta un'eccezione solo per registrarla, wrapparla o convertirla prima di lasciare che venga propagata un'eccezione più specifica. Kotlin rende idiomatica questa pratica.
Rilancio diretto
Per rilanciare un'eccezione, esegua nuovamente throw e: la propagazione continua verso il gestore successivo.
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}")
}
}Wrapping con un'eccezione personalizzata
Passi l'eccezione originale come cause quando ne costruisce una nuova, così da preservare la catena.
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}")
}
}Esaminare la catena delle cause
La proprietà cause collega all'eccezione precedente. La percorra per stampare la causa radice completa.
fun main() {
val e = RuntimeException("top",
RuntimeException("middle",
RuntimeException("root")))
var current: Throwable? = e
while (current != null) {
println(current.message)
current = current.cause
}
}Rilancio selettivo
Intercetti un tipo generico, quindi lo rilanci se NON corrisponde al caso previsto.
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
}Aggiungere contesto
Avvolga l'eccezione in un'eccezione di dominio per aggiungere il contesto che mancava all'originale, come input, ID della richiesta e così via.
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}") }
}Non perda lo stack trace
Quando avvolge un'eccezione, passi sempre l'originale come cause: non crei mai semplicemente una nuova eccezione con lo stesso messaggio ma senza causa. Lo stack trace è la sua risorsa fondamentale per il debugging.
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}")
}
}Rilanciare senza wrapping
Se le serve solo la registrazione, esegua semplicemente throw e dopo la chiamata di log: non è necessario alcun wrapping.
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 per la pulizia durante il rilancio
Utilizzi finally per pulire le risorse anche quando rilancia un'eccezione.
fun process() {
try {
throw RuntimeException("failure")
} finally {
println("cleanup ran")
}
}
fun main() {
try { process() }
catch (e: RuntimeException) { println("caught: ${e.message}") }
}Eccezioni soppresse
Se è lo stesso finally a lanciare un'eccezione, l'eccezione originale viene soppressa per impostazione predefinita. Utilizzi addSuppressed per preservarle entrambe.
fun main() {
val primary = RuntimeException("primary")
val secondary = RuntimeException("from cleanup")
primary.addSuppressed(secondary)
println(primary.suppressed.joinToString { it.message ?: "?" })
}Anti-pattern: ignorare un'eccezione e poi lanciarne un'altra
Catturare un'eccezione e lanciarne una nuova e non correlata (senza causa) distrugge le informazioni utili per il debug. Passi sempre 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 rapida
Quando incapsula un'eccezione in una nuova eccezione, che cosa dovrebbe fare per preservare lo stack trace originale?
Riepilogo
Per rilanciare: throw e. Per incapsulare: lanci una nuova eccezione con cause = e. Preservi sempre la catena delle cause: non costruisca mai un wrapper senza causa. Utilizzi finally per la pulizia e addSuppressed quando la pulizia stessa fallisce.
Domande Frequenti
La lezione «Rilanciare eccezioni e concatenarle» è gratuita?
Sì — il testo completo di «Rilanciare eccezioni e concatenarle» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.
Cosa imparerò in «Rilanciare eccezioni e concatenarle»?
Rilanci selettivamente le eccezioni e racchiuda gli errori di livello inferiore mantenendo la catena delle cause. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Kotlin Academy?
Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Rilanciare eccezioni e concatenarle»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?
Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- try/catch/finally come espressione
- Creare classi di eccezioni personalizzate
- runCatching e Result
- Rilanciare eccezioni e concatenarle