Java-8'de birden fazla özel durumu yakalama


71

Metodumda bulduğum çoklu yakalama özelliğini denerken m1()her şey beklendiği gibi çalışıyor.

Ancak, m2()aynı kodda derlemez. Ben sadece kod satırı sayısını azaltmak için sözdizimini değiştirdim.

public class Main {

    public int m1(boolean bool) {
        try {
            if (bool) {
                throw new Excep1();
            }
            throw new Excep2();
            //This m1() is compiling  abs fine.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    public int m2(boolean b) {
        try {
            throw b ? new Excep1() : new Excep2();
            //This one is not compiling.
        } catch (Excep1 | Excep2 e) {
            return 0;
        }
    }

    private static interface I {
    }

    private static class Excep1 extends Exception implements I {
    }

    private static class Excep2 extends Exception implements I {
    }
}

Yöntem neden m2()derlenmiyor?


22
Hangi derleme hatasını alıyorsunuz?
Gavin

Yanıtlar:


79

İfadenin türü

b ? new Excep1() : new Excep2()

olan Exceptionbu ortak süper tıp beri, Excep1ve Excep2.

Ancak, yakalamıyorsunuz Exception, bu yüzden derleyici bundan şikayet ediyor.

Eğer yakalarsanız Exception, derleme geçecektir:

public int m2(boolean b) {
    try {
        throw b ? new Excep1() : new Excep2();
    } catch (Exception e) {
        return 0;
    }
}

Örneğinizde koşullu üçlü ifadenin türünü açıklayan JLS girişini bulmaya çalıştım.

Tüm bulabildiğim bu ifade 15.25.3 idi. Referans Koşullu Anlatım .

Bir poli ifadesi veya bağımsız bir ifade olarak sayıldığından tamamen emin değilim. Bağımsız olduğunu düşünüyorum (çünkü poli ifadeler bir atama bağlamı veya bir çağırma bağlamı içerir ve bir throwifadenin bunlardan biri olarak sayılmadığını düşünmüyorum ).

Bağımsız bir ifade için: "İkinci ve üçüncü işlenenler aynı türe sahipse (boş tip olabilir), bu koşullu ifadenin türüdür."

Senin durumunda, ikinci ve üçüncü işlenenler üç ortak türleri vardır - Object, Throwableve Exception- bir atış açıklamada İfade ya bir referans türünde bir değişkeni veya değeri göstermek gerekir", çünkü ifadenin tipi, ikincisi ikisinden biri olmalı Throwable türüne atanabilir (§5.2). "

Derleyicinin en özel ortak türü ( Exception) seçtiği ve bu nedenle catch (Exception e)derleme hatasını çözdüğü anlaşılmaktadır .

Ayrıca, iki özel istisnayı iki alt sınıfla değiştirmeye çalıştım IOException, bu durumda catch (IOException e)derleme hatasını çözer.


11
@ Üçlü koşullu ifadenin türü hem 2. hem de 3. işlenenler için ortak olmalıdır. Bu nedenle olamaz Excep1ya Excep2. Sadece olabilir Exception.
Eran

2
15.25.3'teki son madde işaretinin yanıtı şu şekildedir: "Aksi takdirde, ikinci ve üçüncü işlenenler sırasıyla S1 ve S2 türleridir. Koşullu ifadenin türü lub'a (T1, T2) yakalama dönüştürmesinin (§5.1.10) uygulanmasının sonucudur. " Buradaki lub, iki ifadenin paylaştığı en yakın ortak süpertip olan En Küçük Üst Sınır'dır.
Ocak'ta

22

Derleyiciyi şu satırla karıştırıyorsunuz:

throw b ? new Excep1() : new Excep2();

Derleyici, ifadenin sonucunun (atmanın solunda) Exception1 ve Except2 arasındaki ortak süper sınıf olduğunu görür. Catch deyimi Excep1 veya Except2 atmaya çalıştığınızı alamaz.


4

Java, yöntemin atabileceği tüm özel durum türlerini yakalamanızı veya bildirmenizi kısıtlar,

O (/ tümü) her ikisi için ortak ebeveyn için İstisnalar arama ve örneğin, atar gibi yakalamak veya beyan bekliyoruz Excep1uzanır Throwableayrıca Throwable yakalamak zorunda kalacak

İlk durumda Java, attığınızdan Excep1veyaExcep2

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.