Saat mencoba fitur multi-tangkapan yang saya temukan dalam m1()
metode saya semuanya bekerja dengan baik seperti yang diharapkan.
Namun, dalam m2()
kode yang sama tidak dikompilasi. Saya baru saja mengubah sintaks untuk mengurangi jumlah baris kode.
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 {
}
}
Mengapa metode tidak m2()
dikompilasi?
Jawaban:
Jenis ekspresi
adalah
Exception
, karena itulah supertype umum dariExcep1
danExcep2
.Namun, Anda tidak menangkap
Exception
, jadi kompiler mengeluh tentang hal itu.Jika Anda menangkap
Exception
, itu akan melewati kompilasi:Saya mencoba untuk menemukan entri JLS yang menjelaskan jenis ekspresi ternary kondisional dalam contoh Anda.
Yang bisa saya temukan adalah bahwa ungkapan khusus ini adalah 15.25.3. Referensi Ekspresi Bersyarat .
Saya tidak sepenuhnya yakin apakah itu dianggap sebagai ekspresi poli atau ekspresi mandiri. Saya pikir itu standalone (karena ekspresi poli melibatkan konteks penugasan atau konteks doa, dan saya tidak berpikir
throw
pernyataan dianggap sebagai salah satu dari mereka).Untuk ekspresi mandiri: "Jika operan kedua dan ketiga memiliki tipe yang sama (yang mungkin merupakan tipe null), maka itu adalah tipe ekspresi bersyarat."
Dalam kasus Anda, operan kedua dan ketiga memiliki tiga tipe umum -
Object
,Throwable
danException
- tipe ekspresi harus salah satu dari dua yang terakhir, karena, "Ekspresi dalam pernyataan melempar harus menunjukkan variabel atau nilai dari tipe referensi yang ditugaskan (§5.2) ke tipe Throwable. "Tampaknya kompiler memilih tipe umum yang paling spesifik (
Exception
), dan karenanyacatch (Exception e)
memecahkan kesalahan kompilasi.Saya juga mencoba mengganti dua pengecualian khusus Anda dengan dua sub-kelas
IOException
, dalam hal inicatch (IOException e)
menyelesaikan kesalahan kompilasi.sumber
Excep1
atauExcep2
. Itu hanya bisaException
.Anda mengacaukan kompiler dengan baris ini:
Kompilator melihat bahwa hasil dari ekspresi (di sebelah kiri lemparan) adalah kelas super umum antara exception1 dan exception2, yang merupakan pengecualian, dan karenanya tipe efektif yang Anda lempar menjadi pengecualian. Pernyataan tangkapan tidak dapat mengambil bahwa Anda mencoba untuk membuang Excep1 atau exception2.
sumber
Java membatasi Anda untuk menangkap atau mendeklarasikan semua tipe pengecualian yang dapat dilemparkan metode ini,
Ini mencari orang tua umum untuk kedua (/ semua) Pengecualian dan mengharapkan Anda untuk menangkap atau menyatakan sebagai lemparan, misalnya jika
Excep1
meluasThrowable
Anda harus menangkap juga ThrowableDalam kasus pertama, Java yakin Anda melempar
Excep1
atauExcep2
sumber