1. Jenis pengecualian
![Jenis pengecualian](https://cdn.codegym.cc/images/article/4b137035-7e83-4d1e-a2f7-70211e6638b1/1080.jpeg)
Semua pengecualian dibahagikan kepada 4 jenis, yang sebenarnya merupakan kelas yang mewarisi satu sama lain.
Throwable
kelas
Kelas asas untuk semua pengecualian ialah Throwable
kelas. Kelas Throwable
mengandungi kod yang menulis timbunan panggilan semasa (jejak tindanan kaedah semasa) kepada tatasusunan. Kita akan belajar apa itu surih tindanan sedikit kemudian.
Operator lontaran hanya boleh menerima objek yang berasal dari Throwable
kelas. Dan walaupun anda secara teorinya boleh menulis kod seperti throw new Throwable();
, tiada siapa yang biasanya melakukan ini. Tujuan utama kelas Throwable
adalah untuk mempunyai kelas induk tunggal untuk semua pengecualian.
Error
kelas
Kelas pengecualian seterusnya ialah Error
kelas, yang mewarisi Throwable
kelas secara langsung. Mesin Java mencipta objek kelas Error
(dan keturunannya) apabila masalah serius telah berlaku . Contohnya, kerosakan perkakasan, memori tidak mencukupi, dsb.
Biasanya, sebagai pengaturcara, tiada apa yang boleh anda lakukan dalam situasi di mana ralat sedemikian (jenis yang patut Error
dilemparkan) telah berlaku dalam atur cara: ralat ini terlalu serius. Apa yang anda boleh lakukan ialah memberitahu pengguna bahawa program itu ranap dan/atau menulis semua maklumat yang diketahui tentang ralat pada log program.
Exception
kelas
Kelas Exception
dan RuntimeException
adalah untuk ralat biasa yang berlaku dalam pengendalian banyak kaedah. Matlamat setiap pengecualian yang dilemparkan adalah untuk ditangkap oleh catch
blok yang tahu cara mengendalikannya dengan betul.
Apabila kaedah tidak dapat menyelesaikan kerjanya atas sebab tertentu, ia harus segera memberitahu kaedah panggilan dengan membuang pengecualian jenis yang sesuai.
Dalam erti kata lain, jika pembolehubah adalah sama dengan null
, kaedah akan membuang NullPointerException
. Jika hujah yang salah dihantar kepada kaedah, ia akan membuang InvalidArgumentException
. Jika kaedah secara tidak sengaja membahagi dengan sifar, ia akan membuang ArithmeticException
.
RuntimeException
kelas
RuntimeExceptions
ialah subset daripada Exceptions
. Kita juga boleh mengatakan bahawa RuntimeException
ia adalah versi ringan bagi pengecualian biasa ( Exception
) — lebih sedikit keperluan dan sekatan dikenakan ke atas pengecualian tersebut
Anda akan mengetahui perbezaan antara Exception
dan RuntimeException
kemudian.
2. Throws
: pengecualian diperiksa
Semua pengecualian Java jatuh ke dalam 2 kategori: ditandai dan dinyahtanda .
Semua pengecualian yang mewarisi RuntimeException
atau Error
dianggap pengecualian tidak ditanda . Semua yang lain disemak pengecualian .
Dua puluh tahun selepas pengecualian yang diperiksa diperkenalkan, hampir setiap pengaturcara Java menganggap ini sebagai pepijat. Dalam rangka kerja moden yang popular, 95% daripada semua pengecualian tidak ditandai. Bahasa C#, yang hampir menyalin Java dengan tepat, tidak menambah pengecualian yang diperiksa .
Apakah perbezaan utama antara pengecualian yang disemak dan tidak disemak ?
Terdapat keperluan tambahan yang dikenakan ke atas pengecualian yang disemak . Secara kasarnya, mereka adalah ini:
Keperluan 1
Jika kaedah melemparkan pengecualian yang ditandai , ia mesti menunjukkan jenis pengecualian dalam tandatangannya . Dengan cara itu, setiap kaedah yang memanggilnya menyedari bahawa "pengecualian yang bermakna" ini mungkin berlaku di dalamnya.
Nyatakan pengecualian yang disemak selepas parameter kaedah selepas throws
kata kunci (jangan gunakan throw
kata kunci secara tidak sengaja). Ia kelihatan seperti ini:
type method (parameters) throws exception
Contoh:
pengecualian diperiksa | pengecualian tidak ditanda |
---|---|
|
|
Dalam contoh di sebelah kanan, kod kami membuang pengecualian yang tidak ditanda — tiada tindakan tambahan diperlukan. Dalam contoh di sebelah kiri, kaedah membuang pengecualian yang ditandai , jadi throws
kata kunci ditambahkan pada tandatangan kaedah bersama-sama dengan jenis pengecualian.
Jika kaedah menjangkakan untuk membuang berbilang pengecualian yang ditandakan , kesemuanya mesti dinyatakan selepas throws
kata kunci, dipisahkan dengan koma. Perintah itu tidak penting. Contoh:
public void calculate(int n) throws Exception, IOException
{
if (n == 0)
throw new Exception("n is null!");
if (n == 1)
throw new IOException("n is 1");
}
Keperluan 2
Jika anda memanggil kaedah yang telah menyemak pengecualian dalam tandatangannya, anda tidak boleh mengabaikan fakta bahawa kaedah itu membuangnya.
Anda mesti sama ada menangkap semua pengecualian tersebut dengan menambahkan catch
blok untuk setiap satu, atau dengan menambahkannya pada throws
klausa untuk kaedah anda.
Seolah-olah kita berkata, " Pengecualian ini sangat penting sehingga kita mesti menangkapnya. Dan jika kita tidak tahu cara mengendalikannya, maka sesiapa yang mungkin memanggil kaedah kita mesti dimaklumkan bahawa pengecualian tersebut boleh berlaku di dalamnya.
Contoh:
Bayangkan bahawa kita sedang menulis kaedah untuk mencipta dunia yang dihuni oleh manusia. Bilangan awal orang diluluskan sebagai hujah. Jadi kita perlu menambah pengecualian jika terdapat terlalu sedikit orang.
Mencipta Bumi | Catatan |
---|---|
|
Kaedah ini berpotensi membuang dua pengecualian yang diperiksa :
|
Panggilan kaedah ini boleh dikendalikan dalam 3 cara:
1. Jangan tangkap sebarang pengecualian
Ini paling kerap dilakukan apabila kaedah tidak tahu cara mengendalikan keadaan dengan betul.
Kod | Catatan |
---|---|
|
Kaedah panggilan tidak menangkap pengecualian dan mesti memberitahu orang lain tentangnya: ia menambahkannya pada klausanya throws sendiri |
2. Tangkap beberapa pengecualian
Kami menangani kesilapan yang boleh kami tangani. Tetapi yang kita tidak faham, kita buang ke kaedah panggilan. Untuk melakukan ini, kita perlu menambah nama mereka pada klausa lontaran:
Kod | Catatan |
---|---|
|
Pemanggil hanya menangkap satu pengecualian yang diperiksaLonelyWorldException — . Pengecualian lain mesti ditambahkan pada tandatangannya, menunjukkannya selepas throws kata kunci |
3. Tangkap semua pengecualian
Jika kaedah tidak membuang pengecualian kepada kaedah panggilan, maka kaedah panggilan sentiasa yakin bahawa semuanya berfungsi dengan baik. Dan ia tidak akan dapat mengambil sebarang tindakan untuk membetulkan situasi yang luar biasa.
Kod | Catatan |
---|---|
|
Semua pengecualian terperangkap dalam kaedah ini. Pemanggil akan yakin bahawa semuanya berjalan lancar. |
3. Pengecualian pembalut
Pengecualian yang disemak kelihatan hebat dalam teori, tetapi ternyata menjadi kekecewaan yang besar dalam amalan.
Katakan anda mempunyai kaedah yang sangat popular dalam projek anda. Ia dipanggil dari ratusan tempat dalam program anda. Dan anda memutuskan untuk menambah pengecualian baru yang ditandakan padanya. Dan mungkin pengecualian yang disemak ini benar-benar penting dan sangat istimewa sehingga hanya main()
kaedah yang tahu apa yang perlu dilakukan jika ia ditangkap.
Ini bermakna anda perlu menambah pengecualian yang ditandakan pada throws
klausa setiap kaedah yang memanggil kaedah super popular anda . Begitu juga dalam throws
klausa semua kaedah yang memanggil kaedah tersebut. Dan kaedah yang memanggil kaedah tersebut.
Akibatnya, throws
klausa separuh daripada kaedah dalam projek mendapat pengecualian diperiksa baharu . Dan sudah tentu projek anda dilindungi oleh ujian, dan kini ujian tidak disusun. Dan kini anda perlu mengedit klausa lontaran dalam ujian anda juga.
Dan kemudian semua kod anda (semua perubahan dalam ratusan fail) perlu disemak oleh pengaturcara lain. Dan pada ketika ini kami bertanya kepada diri sendiri mengapa kami membuat banyak perubahan berdarah pada projek itu? Hari bekerja dan ujian yang rosak — semuanya demi menambah satu pengecualian yang telah ditandakan ?
Dan sudah tentu, masih terdapat masalah yang berkaitan dengan pewarisan dan kaedah mengatasi. Masalah yang datang daripada pengecualian yang diperiksa adalah lebih besar daripada manfaatnya. Intinya ialah kini hanya sedikit orang yang menyukainya dan hanya sedikit orang yang menggunakannya.
Walau bagaimanapun, masih terdapat banyak kod (termasuk kod perpustakaan Java standard) yang mengandungi pengecualian yang disemak ini . Apa yang perlu dilakukan dengan mereka? Kita tidak boleh mengabaikan mereka, dan kita tidak tahu bagaimana untuk mengendalikannya.
Pengaturcara Java mencadangkan untuk membungkus pengecualian yang diperiksa dalam RuntimeException
. Dalam erti kata lain, tangkap semua pengecualian yang ditandakan dan kemudian buat pengecualian yang tidak ditandakan (contohnya, RuntimeException
) dan buangnya. Melakukannya kelihatan seperti ini:
try
{
// Code where a checked exception might occur
}
catch(Exception exp)
{
throw new RuntimeException(exp);
}
Ia bukan penyelesaian yang sangat cantik, tetapi tiada apa-apa jenayah di sini: pengecualian hanya disumbat di dalam RuntimeException
.
Jika dikehendaki, anda boleh mendapatkannya dengan mudah dari sana. Contoh:
Kod | Catatan |
---|---|
|
Dapatkan pengecualian yang disimpan di dalam RuntimeException objek. Pembolehubah cause mungkin null Tentukan jenisnya dan tukarkannya kepada jenis pengecualian yang diperiksa . |
4. Menangkap pelbagai pengecualian
Pengaturcara sangat tidak suka menduplikasi kod. Mereka juga mengemukakan prinsip pembangunan yang sepadan: Jangan Ulangi Sendiri (KERING) . Tetapi apabila mengendalikan pengecualian, terdapat keadaan yang kerap apabila try
blok diikuti oleh beberapa catch
blok dengan kod yang sama.
Atau mungkin terdapat 3 catch
blok dengan kod yang sama dan 2 catch
blok lagi dengan kod yang serupa. Ini adalah situasi standard apabila projek anda mengendalikan pengecualian secara bertanggungjawab.
Bermula dengan versi 7, dalam bahasa Java menambahkan keupayaan untuk menentukan berbilang jenis pengecualian dalam satu catch
blok. Ia kelihatan seperti ini:
try
{
// Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
// Exception handling code
}
Anda boleh mempunyai seberapa banyak catch
blok yang anda mahu. Walau bagaimanapun, satu catch
blok tidak boleh menentukan pengecualian yang mewarisi satu sama lain. Dalam erti kata lain, anda tidak boleh menulis catch ( Exception
| RuntimeException
e), kerana RuntimeException
kelas mewarisi Exception
.
5. Pengecualian tersuai
Anda sentiasa boleh membuat kelas pengecualian anda sendiri. Anda hanya membuat kelas yang mewarisi RuntimeException
kelas. Ia akan kelihatan seperti ini:
class ClassName extends RuntimeException
{
}
Kami akan membincangkan butiran semasa anda mempelajari OOP, warisan, pembina dan kaedah mengatasi.
Walau bagaimanapun, walaupun anda hanya mempunyai kelas mudah seperti ini (sepenuhnya tanpa kod), anda masih boleh membuang pengecualian berdasarkannya:
Kod | Catatan |
---|---|
|
Buang yang tidak bertanda MyException . |
Dalam pencarian Java Multithreading , kami akan menyelam lebih mendalam untuk bekerja dengan pengecualian tersuai kami sendiri.
GO TO FULL VERSION