Cómo detectar muchas excepciones al mismo tiempo en Kotlin


84
try { 

} catch (ex: MyException1, MyException2 ) {
    logger.warn("", ex)
}

o

try { 

} catch (ex: MyException1 | MyException2 ) {
    logger.warn("", ex)
}

Como resultado, un error de compilación: Unresolved reference: MyException2.

¿Cómo puedo detectar muchas excepciones al mismo tiempo en Kotlin?

Respuestas:


95

Actualización: vote por el siguiente número KT-7128 si desea que esta función llegue a Kotlin.Gracias @Cristan

Según este hilo, esta función no es compatible en este momento.

abreslav - Equipo JetBrains

No por el momento, pero está sobre la mesa.

Sin embargo, puede imitar la captura múltiple:

try {
    // do some work
} catch (ex: Exception) {
    when(ex) {
        is IllegalAccessException, is IndexOutOfBoundsException -> {
            // handle those above
        }
        else -> throw ex
    }
}

2
Estoy copiando la pdvriezerespuesta aquí: This certainly works, but is slightly less efficient as the caught exception is explicit to the jvm (so a non-processed exception will not be caught and rethrown which would be the corollary of your solution)
solidak

1
@IARI La elsecláusula vuelve a generar la excepción no deseada .
miensol


2
Incluso si descarta los argumentos de elegancia y fealdad a un lado, Kotlin (que dice ser conciso) es en realidad el doble de detallado que Java en este caso
Phileo99

2
Detekt lo marca porque está detectando una excepción demasiado genérica ;-)
kenyee

8

Para agregar a la respuesta de miensol : aunque la captura múltiple en Kotlin aún no es compatible, hay más alternativas que deben mencionarse.

Aparte de try-catch-when, también puede implementar un método para imitar una captura múltiple. Aquí tienes una opción:

fun (() -> Unit).catch(vararg exceptions: KClass<out Throwable>, catchBlock: (Throwable) -> Unit) {
    try { 
        this() 
    } catch (e: Throwable) {
        if (e::class in exceptions) catchBlock(e) else throw e
    }
}

Y usarlo se vería así:

fun main(args: Array<String>) {
    // ...
    {
        println("Hello") // some code that could throw an exception

    }.catch(IOException::class, IllegalAccessException::class) {
        // Handle the exception
    }
}

Querrá usar una función para producir una lambda en lugar de usar una lambda sin procesar como se muestra arriba (de lo contrario, se encontrará con "MANY_LAMBDA_EXPRESSION_ARGUMENTS" y otros problemas con bastante rapidez). Algo como fun attempt(block: () -> Unit) = blockfuncionaría.

Por supuesto, es posible que desee encadenar objetos en lugar de lambdas para componer su lógica de manera más elegante o para comportarse de manera diferente a un simple try-catch.

Solo recomendaría usar este enfoque en lugar de miensol si está agregando alguna especialización . Para usos simples de captura múltiple, una whenexpresión es la solución más simple.


Si lo entiendo correctamente, pasa clases en su captura, pero param exceptionstoma objetos.
nllsdfx

eres increíble hombre @aro, gracias por brindar esta alternativa
mochadwi

Esta alternativa es buena, gracias Aro :) Mejor que nada. Sin embargo, espero que lleguen a esa función, aunque mi problema KT-7128 se abrió hace 5 años :-)
zdenda.online

-1

El ejemplo de aro es muy bueno, pero si hay herencias, no funcionará como en Java.

Su respuesta me inspiró a escribir una función de extensión para eso. Para permitir también clases heredadas, debe verificar en instancelugar de comparar directamente.

inline fun multiCatch(runThis: () -> Unit, catchBlock: (Throwable) -> Unit, vararg exceptions: KClass<out Throwable>) {
try {
    runThis()
} catch (exception: Exception) {
    val contains = exceptions.find {
        it.isInstance(exception)
    }
    if (contains != null) catchBlock(exception)
    else throw exception
}}

Para ver cómo se usa, puede echar un vistazo a mi biblioteca en GitHub aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.