如何在Kotlin同时捕获许多例外

How to catch many exceptions at the same time in Kotlin

1
2
3
4
5
try {

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

1
2
3
4
5
try {

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

作为一个结果,Unresolved reference: MyException2编译错误。

我怎么能在同一时间,有许多例外kotlin在线?


更新:如果您希望此功能在Kotlin着陆,请投票选择以下问题KT-7128。谢谢@ Cristan

根据此线程,目前不支持此功能。

abreslav - JetBrains Team

Not at the moment, but it is on the table

您可以模拟多重捕捉:

1
2
3
4
5
6
7
8
9
10
try {
    // do some work
} catch (ex: Exception) {
    when(ex) {
        is IllegalAccessException, is IndexOutOfBoundsException -> {
            // handle those above
        }
        else -> throw ex
    }
}


除此之外,Miensol的回答是:虽然目前还不支持科特林的多重捕捞,但还有更多的替代方案需要提及。

除了try-catch-when,您还可以实现一个方法来模拟多捕获。这里有一个选项:

1
2
3
4
5
6
7
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
    }
}

使用它的方式如下:

1
2
3
4
5
6
7
8
9
fun main(args: Array<String>) {
    // ...
    {
        println("Hello") // some code that could throw an exception

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

您将希望使用一个函数来生成lambda,而不是使用上面所示的原始lambda(否则您将很快遇到"许多lambda表达式参数"和其他问题)。像fun attempt(block: () -> Unit) = block这样的东西是可行的。

当然,您可能希望链接对象而不是lambda,以便更优雅地组合逻辑,或者与简单的旧的try-catch行为不同。

我只建议您在Miensol's上使用这种方法,如果您正在添加一些专业化的话。对于简单的多捕获使用,when表达式是最简单的解决方案。


来自ARO的例子非常好,但是如果有继承,它就不会像Java那样工作。

你的回答激励我为它编写一个扩展函数。为了允许继承类,您必须检查instance,而不是直接比较。

1
2
3
4
5
6
7
8
9
10
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
}}

要了解如何使用,您可以在Github上的我的库中查看