如何在 Kotlin 同时抓住许多例外?

try {


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

或者

try {


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

结果,出现编译错误: Unresolved reference: MyException2

在 Kotlin,我怎样才能同时抓住许多例外?

63590 次浏览

更新: 如果你想让这个功能在 Kotlin 登陆,请为下一期的 abc 0投票。 < i > 谢谢@Cristan

根据 线的说法,这个功能目前还不支持。

Abreslav-JetBrains 团队

现在还没有,但已经摆在桌面上了

不过,你可以模仿多捕获:

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

作为对 Miensol的回答的补充: 尽管 Kotlin 还不支持多鱼种捕捞,但是还有更多的替代方案值得一提。

除了 try-catch-when之外,您还可以实现一个方法来模拟 multi-catch:

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

使用它会看起来像:

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


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

您可能希望使用一个函数来生成一个 lambda,而不是像上面所示的那样使用一个原始的 lambda (否则,您将很快遇到“ MANY _ LAMBDA _ EXExpression _ ARGUMENT”和其他问题)。像 fun attempt(block: () -> Unit) = block这样的就可以了。

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

如果您正在添加一些专门化 ,那么我只推荐使用这种方法而不是 Miensol。对于简单的多捕获用法,when表达式是最简单的解决方案。

来自 Aro的示例非常好,但是如果存在继承,它就不能像 Java 那样工作。

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

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 给你上查看我的库

在 Kotlin,你可以这样做:

try{
} catch(e: MyException1){
} catch(e: MyException2){
} catch(e: MyException3){
} [...]

通过这种方式,您可以获取多个 Catch,并且使用 MultiCatch 方法可以检测异常

import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf


class NegetiveNumber : Exception()
class StringFalse : Exception()


fun <R> Exception.multiCatch(vararg classes: KClass<*>, block: () -> R): R {
return if (classes.any {
this::class.isSubclassOf(it)
}) block()
else throw this
}
class Human() {
var name = ""
set(name) {
if (name.isEmpty()) {
throw StringFalse()
} else {
field = name
}
}
var age = 0
set(age) {
if (age <= 0) {
throw NegetiveNumber()
} else {
field = age
}
}
}
fun main() {
val human = Human()
human.name = "Omidreza"
human.age = 0


try {
println(human.name)
println(human.age)
} catch (e: Exception) {
  



e.multiCatch(NegetiveNumber::class, StringFalse::class) {
println(e.message)
}
}finally {
println("end")
}
}

这里是 multiCatch ():

fun <R> Exception.multiCatch(vararg classes: KClass<*>, block: () -> R): R {
return if (classes.any {
this::class.isSubclassOf(it)
}) block()
else throw this
}