捕获由Kotlin中给定的KClass <in Exception>定义的异常?

时间:2019-12-19 12:48:55

标签: generics kotlin

例如,我想编写一个测试,该测试应捕获Exception的特定子类。 为此,我写

fun test(klazz: KClass<in Exception>) {
    try {
        ...
    } catch (e: Exception) {
        if (!kclazz.isInstance(e)) {
            throw e
        } else {
            ...
        }
    }
}

有没有一种更简单的方法可以做到这一点?因为在这种情况下我不希望添加额外的类检查,而只是进一步抛出捕获的异常是一个很好的解决方案。有什么类似下面的代码?

fun test(klazz: KClass<in Exception>) {
    try {
        ...
    } catch (e: klazz(smth here)) {
        ...
    }
}

我几乎可以肯定没有,因为我尝试了许多不同的方法。但是在这种情况下,如果有人可以解释为什么不可能的话,那将很酷。

2 个答案:

答案 0 :(得分:0)

不可能,因为语法

catchBlock
(used by tryExpression)
  : 'catch' '(' annotation* simpleIdentifier ':' type ')' block
  ;

requires a type in that position,并且类型无法依赖klazz(在Kotlin中)之类的值。

我尝试了

inline fun <reified E : Exception> test() {
    try {
        ...
    } catch (e: E) {
        ...
    }
}

,但这是专门排除的apparently because it didn't work properly when it wasn't。当然了

} catch (e: Exception) {
    if (e is E) ...
}

确实有效,并且可能比通过KClass更好。

答案 1 :(得分:0)

我使用此高级实用程序功能做了类似的事情:

/**
 * Asserts that the given block of code throws an exception of the specified type.
 *
 * This is much more fine-grained than `@Test(expected = ...)`, letting
 * you check that the exception was thrown by specific line(s) of code.
 *
 * @return The exception thrown.  This lets you make further tests on it
 *         (e.g. in an `also{}` block).
 * @throws AssertionError if no exception, or one of another type, was thrown.
 */
inline fun <reified T: Exception> assertThrows(exceptionClass: KClass<T> = T::class, block: () -> Unit): T {
    try {
        block()
        throw AssertionError("Should have thrown ${exceptionClass.simpleName}!")
    } catch (x: Exception) {
        if (x is T)
            return x
        throw AssertionError("Should have thrown ${exceptionClass.simpleName}, but threw $x!")
    }
}

您可以在单元测试中使用它,例如:

@Test fun myTest() {
    assertThrows(NullPointerException::class) {
        // Some code that should throw a NullPointerException...
    }
}

(虽然不止一行,但还是很简洁,而且读起来不错。)