Kotlin'de aynı anda birçok istisna nasıl yakalanır?


87
try { 

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

veya

try { 

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

Sonuç olarak, bir derleme hatası: Unresolved reference: MyException2.

Kotlin'de aynı anda birçok istisnayı nasıl yakalayabilirim?

Yanıtlar:


100

Güncelleme: Bu özelliğin Kotlin'e inmesini istiyorsanız , aşağıdaki KT-7128 sayısı için oy verin . Teşekkürler @Cristan

Bu konuya göre bu özellik şu anda desteklenmemektedir.

abreslav - JetBrains Ekibi

Şu anda değil ama masanın üstünde

Yine de çoklu yakalama işlemini taklit edebilirsiniz:

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

2
Ben taklit ediyorum pdvriezeburada cevap: 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 elseMadde, istenmeyen istisnayı yeniden atar .
miensol

2
@IARI Orijinal
miensol

2
Zerafet ve çirkinlik argümanlarını bir kenara atsanız bile, Kotlin (özlü olduğunu iddia eder) aslında bu durumda Java'nın 2
katı

2
Bu, Detekt tarafından işaretleniyor çünkü çok genel bir istisna yakaladınız ;-)
kenyee

8

Miensol'ün cevabına eklemek için: Kotlin'de çoklu yakalama henüz desteklenmese de, belirtilmesi gereken daha fazla alternatif var.

Bunun yanı sıra, try-catch-whençoklu yakalamayı taklit etmek için bir yöntem de uygulayabilirsiniz. İşte bir seçenek:

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

Ve bunu kullanmak şöyle görünür:

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

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

Yukarıda gösterildiği gibi ham bir lambda kullanmak yerine bir lambda üretmek için bir işlev kullanmak isteyeceksiniz (aksi takdirde "MANY_LAMBDA_EXPRESSION_ARGUMENTS" ve diğer sorunlarla oldukça hızlı bir şekilde karşılaşacaksınız). fun attempt(block: () -> Unit) = blockİşe yarayacak gibi bir şey .

Elbette, mantığınızı daha zarif bir şekilde oluşturmak için lambdalar yerine nesneleri zincirlemek veya düz eski bir deneme yakalamadan farklı davranmak isteyebilirsiniz.

Bu yaklaşımı miensollere göre sadece biraz uzmanlık ekliyorsanız kullanmanızı tavsiye ederim . Basit çoklu yakalama kullanımları için bir whenifade en basit çözümdür.


Eğer doğru anlarsam exceptions, yakaladığınız derslerde geçersiniz ama param nesneleri alır.
nllsdfx

Sen müthiş adam @aro Bu alternatifi sunmak için teşekkürler
mochadwi

Bu alternatif iyi, teşekkürler Aro :) Hiç yoktan iyidir. Ancak, KT-7128
numaralı sayım

0

Aro'dan alınan örnek çok iyidir, ancak miras varsa, Java'daki gibi çalışmayacaktır.

Cevabınız bunun için bir uzantı işlevi yazmam için bana ilham verdi. Ayrıca devralınan sınıflara izin vermek için instancedoğrudan karşılaştırmak yerine kontrol etmeniz gerekir .

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

Nasıl kullanılacağını görmek için GitHub'daki kitaplığıma buradan bakabilirsiniz.


"-1" in nedeni nedir? deneyin {...} catch (X | Y e) {...} Java'da da kalıtımı denetler. Bu cevap Java'nın davranışını taklit eder, örneğin IOException'ı birçok farklı alt türle yakalamak için daha uygundur.
Dmitry Ovchinnikov
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.