1. Pengenalan
Dalam tutorial ini, kita akan melihat lontaran dan lemparan di Java. Kami akan menerangkan kapan kami harus menggunakannya.
Seterusnya, kami akan menunjukkan beberapa contoh penggunaan asasnya.
2. Baling dan Melemparkan
Mari mulakan dengan pengenalan pantas. Kata kunci ini berkaitan dengan pengendalian pengecualian. Pengecualian ditimbulkan apabila aliran normal aplikasi kami terganggu.
Mungkin ada banyak alasan. Pengguna boleh menghantar data input yang salah. Kami terputus hubungan atau keadaan tidak dijangka yang lain mungkin berlaku. Pengendalian pengecualian yang baik adalah kunci untuk memastikan aplikasi kita berfungsi setelah munculnya saat-saat yang tidak menyenangkan itu.
Kami menggunakan kata kunci lemparan untuk membuang pengecualian dari kod secara eksplisit . Ini mungkin kaedah atau blok statik. Pengecualian ini mestilah subkelas Throwable. Ia juga boleh dilemparkan sendiri. Kami tidak dapat melontarkan banyak pengecualian dengan sekali lontaran .
Kata kunci balingan boleh diletakkan dalam deklarasi kaedah. Ini menunjukkan pengecualian mana yang boleh dilemparkan dari kaedah ini. Kita mesti menangani pengecualian ini dengan cubaan.
Kedua-dua kata kunci ini tidak boleh ditukar ganti!
3. Buang di Jawa
Mari kita lihat contoh asas dengan membuang pengecualian dari kaedah.
Pertama sekali, bayangkan bahawa kita menulis kalkulator ringkas. Salah satu operasi asas aritmetik adalah pembahagian. Oleh kerana itu, kami diminta untuk menerapkan fitur ini:
public double divide(double a, double b) { return a / b; }
Kerana kita tidak dapat membahagi dengan sifar, kita perlu menambahkan beberapa pengubahsuaian pada kod yang ada. Nampaknya ini adalah saat yang baik untuk meningkatkan pengecualian.
Mari lakukan ini:
public double divide(double a, double b) { if (b == 0) { throw new ArithmeticException("Divider cannot be equal to zero!"); } return a / b; }
Seperti yang anda lihat, kami telah menggunakan ArithmeticException yang sangat sesuai dengan keperluan kami. Kita boleh melewati satu parameter String konstruktor yang merupakan mesej pengecualian.
3.1. Amalan yang Baik
Kita harus selalu memilih pengecualian yang paling khusus. Kita perlu mencari kelas yang paling sesuai untuk acara luar biasa kita. Contohnya, buang NumberFormatException dan bukannya IllegalArgumentException. Kita harus mengelakkan membuang Pengecualian yang tidak spesifik .
Sebagai contoh, terdapat kelas Integer dalam pakej java.lang . Mari kita lihat salah satu deklarasi kaedah kilang:
public static Integer valueOf(String s) throws NumberFormatException
Ini adalah kaedah kilang statik yang membuat instance Integer dari String. Sekiranya String input salah , kaedah akan membuang NumberFormatException.
Idea yang baik adalah menentukan pengecualian kita sendiri yang lebih deskriptif. Di kelas Kalkulator kami yang boleh menjadi contoh DivideByZeroException
Mari lihat contoh pelaksanaan:
public class DivideByZeroException extends RuntimeException { public DivideByZeroException(String message) { super(message); } }
3.2. Membungkus Pengecualian Sedia Ada
Kadang-kadang kita ingin membungkus pengecualian yang ada menjadi pengecualian yang ditentukan oleh kita.
Mari kita mulakan dengan menentukan pengecualian kita sendiri:
public class DataAcessException extends RuntimeException { public DataAcessException(String message, Throwable cause) { super(message, cause); } }
Pembina mengambil dua parameter: mesej pengecualian, dan sebab, yang mungkin merupakan subkelas Throwable.
Mari tulis pelaksanaan palsu untuk fungsi findAll () :
public List findAll() throws SQLException { throw new SQLException(); }
Sekarang, di SimpleService mari kita memanggil fungsi repositori, yang boleh menghasilkan SQLException:
public void wrappingException() { try { personRepository.findAll(); } catch (SQLException e) { throw new DataAccessException("SQL Exception", e); } }
Kami melemparkan semula SQLException yang dibungkus dengan pengecualian kami sendiri yang disebut DataAccessException. Semuanya disahkan dengan ujian berikut:
@Test void whenSQLExceptionIsThrown_thenShouldBeRethrownWithWrappedException() { assertThrows(DataAccessException.class, () -> simpleService.wrappingException()); }
Terdapat dua sebab untuk melakukan ini. Pertama sekali, kami menggunakan pembungkus pengecualian, kerana selebihnya kod tidak perlu mengetahui tentang setiap kemungkinan pengecualian dalam sistem.
Komponen tahap yang lebih tinggi juga tidak perlu mengetahui tentang komponen tahap bawah, juga pengecualian yang mereka lemparkan.
3.3. Multi-Catch dengan Java
Kadang kala, kaedah yang kita gunakan boleh membuang banyak pengecualian.
Mari lihat blok cubaan tangkapan yang lebih luas:
try { tryCatch.execute(); } catch (ConnectionException | SocketException ex) { System.out.println("IOException"); } catch (Exception ex) { System.out.println("General exception"); }
Yang melaksanakan kaedah boleh membuang tiga pengecualian: SocketException, ConnectionException, Pengecualian. Blok tangkapan pertama akan menangkap ConnectionException atau SocketException . Blok tangkapan kedua akan menangkap Pengecualian atau subkelas Pengecualian lain. Ingatlah, bahawa kita harus selalu mendapat pengecualian yang lebih terperinci terlebih dahulu.
Kami boleh menukar susunan blok tangkapan kami. Kemudian, kami tidak akan menangkap SocketException dan ConnectionException kerana semuanya akan masuk ke tangkapan dengan Pengecualian .
4. Lontaran di Jawa
Kami menambah lontaran ke deklarasi kaedah.
Let's take a look at one of our previous method declaration:
public static void execute() throws SocketException, ConnectionException, Exception
The method may throw multiple exceptions. They are comma-separated at the end of a method declaration. We can put both, checked and unchecked exceptions in the throws. We have described the difference between them below.
4.1. Checked and Unchecked Exceptions
A checked exception means that it's checked at the compile time. Note, that we must handle this exception. Otherwise, a method must specify an exception by using throws keyword.
The most common checked exceptions are IOException, FileNotFoundException, ParseException. FileNotFoundException may be thrown when we create FileInputStream from File.
There's a short example:
File file = new File("not_existing_file.txt"); try { FileInputStream stream = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); }
We can avoid using try-catch block by adding throws to the method declaration:
private static void uncheckedException() throws FileNotFoundException { File file = new File("not_existing_file.txt"); FileInputStream stream = new FileInputStream(file); }
Unfortunately, a higher level function still has to handle this exception. Otherwise, we have to put this exception in method declaration with throws keyword.
As the opposite, unchecked exceptions aren't checked at the compile time.
The most common unchecked exceptions are: ArrayIndexOutOfBoundsException, IllegalArgumentException, NullPointerException.
Unchecked exceptions are thrown during runtime. The following code will throw a NullPointerException. Probably it's one of the most common exceptions in Java.
Calling a method on a null reference will result in this exception:
public void runtimeNullPointerException() { String a = null; a.length(); }
Let's verify this behavior in the test:
@Test void whenCalled_thenNullPointerExceptionIsThrown() { assertThrows(NullPointerException.class, () -> simpleService.runtimeNullPointerException()); }
Ingatlah bahawa kod dan ujian ini tidak masuk akal. Ini hanya untuk tujuan pembelajaran untuk menjelaskan pengecualian runtime.
Di Java, setiap subkelas Kesalahan dan RuntimeException adalah pengecualian yang tidak dicentang . Pengecualian yang diperiksa adalah perkara lain di bawah kelas Throwable .
5. Kesimpulan
Dalam artikel ini, kami telah membincangkan perbezaan antara dua kata kunci Java: balingan dan lemparan. Kami telah melalui penggunaan asas dan membincangkan sedikit mengenai amalan baik . Kemudian kami telah membincangkan pengecualian yang dicentang dan tidak dicentang.
Seperti biasa, kod sumber boleh didapati di GitHub kami.
Sekiranya anda ingin mempelajari lebih lanjut mengenai Pengecualian di Java, lihat artikel kami mengenai pengecualian Java.