Kotlinで同時に多くの例外をキャッチする方法


87
try { 

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

または

try { 

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

その結果、コンパイルエラー:Unresolved reference: MyException2

Kotlinで同時に多くの例外をキャッチするにはどうすればよいですか?

回答:


100

更新:この機能をKotlinに導入したい場合は、次の問題KT-7128に投票してください。ありがとう@Cristan

このスレッドによると、この機能は現時点ではサポートされていません。

abreslav-JetBrainsチーム

現時点ではありませんが、テーブルの上にあります

ただし、マルチキャッチを模倣することはできます。

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

2
私はpdvriezeここに返信をコピーしています: 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 2017

1
@IARIelse句は、不要な例外を再スローします。
miensol 2017年


2
優雅さと醜さの議論を捨てても、Kotlin(簡潔であると主張している)は、この場合、実際にはJavaの2倍冗長です
Phileo99 2017

2
あまりにも一般的な例外をキャッチしているため、
Detekt

8

miensolの回答に追加するには、Kotlinでのマルチキャッチはまだサポートされていませんが、言及する必要のある代替案が他にもあります。

とは別にtry-catch-when、マルチキャッチを模倣するメソッドを実装することもできます。1つのオプションがあります:

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

上記のように生のラムダを使用するのではなく、関数を使用してラムダを生成することをお勧めします(そうしないと、「MANY_LAMBDA_EXPRESSION_ARGUMENTS」やその他の問題がすぐに発生します)。のようなものfun attempt(block: () -> Unit) = blockが機能します。

もちろん、ロジックをよりエレガントに構成したり、従来のtry-catchとは異なる動作をしたりするために、ラムダの代わりにオブジェクトをチェーンしたい場合があります。

専門分野を追加する場合にのみ、miensolよりもこのアプローチを使用することをお勧めします。単純なマルチキャッチの使用の場合、when式が最も単純なソリューションです。


私が正しく理解していれば、catchでクラスを渡しますが、paramexceptionsはオブジェクトを受け取ります。
nllsdfx 2018年

あなたしている素晴らしい男@aro、この代替を提供するためのおかげで
mochadwi

この代替案は良いです、ありがとうアロ:)何もないよりはましです。しかし、私は私の問題のKT-7128は、5年前にオープンしたが、彼らはその機能に着くことを願っています:-)
zdenda.online

0

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の私のライブラリをご覧ください。


「-1」の理由は何ですか?Javaのtry {...} catch(X | Y e){...}も継承をチェックします。この回答はJavaの動作を模倣しています。たとえば、多くの異なるサブタイプでIOExceptionをキャッチする場合に便利です。
ドミトリー・オフチニコフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.