JavaRush /Java Blog /Random-ID /Pengecualian di Jawa: penangkapan dan penanganan

Pengecualian di Jawa: penangkapan dan penanganan

Dipublikasikan di grup Random-ID
Halo! Saya tidak suka membocorkannya kepada Anda, tetapi sebagian besar pekerjaan seorang programmer adalah menangani kesalahan. Dan paling sering - dengan miliknya sendiri. Kebetulan tidak ada orang yang tidak melakukan kesalahan. Dan tidak ada program seperti itu juga. Tentu saja, hal utama saat mengatasi suatu kesalahan adalah memahami penyebabnya. Dan mungkin ada banyak alasan untuk hal tersebut dalam program ini. Pada satu titik, pencipta Java dihadapkan pada pertanyaan: apa yang harus dilakukan dengan potensi kesalahan dalam program ini? Menghindarinya sepenuhnya adalah tidak realistis. Pemrogram dapat menulis sesuatu yang bahkan tidak mungkin untuk dibayangkan :) Ini berarti perlu dibangun mekanisme untuk menangani kesalahan ke dalam bahasa. Dengan kata lain, jika terjadi kesalahan pada program, maka diperlukan skrip untuk pekerjaan selanjutnya. Apa sebenarnya yang harus dilakukan program ketika terjadi kesalahan? Hari ini kita akan berkenalan dengan mekanisme ini. Dan itu disebut “Pengecualian .

Apa pengecualian di Jawa

Pengecualian adalah beberapa situasi luar biasa dan tidak terencana yang terjadi selama pengoperasian program. Ada banyak contoh pengecualian di Java. Misalnya, Anda menulis kode yang membaca teks dari file dan menampilkan baris pertama ke konsol.
public class Main {

   public static void main(String[] args) throws IOException {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
       String firstString = reader.readLine();
       System.out.println(firstString);
   }
}
Tapi file seperti itu tidak ada! Hasil dari program ini akan menjadi pengecualian - FileNotFoundException. Kesimpulan:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Setiap pengecualian diwakili oleh kelas terpisah di Java. Semua kelas pengecualian berasal dari “nenek moyang” yang sama - kelas induk Throwable. Nama kelas pengecualian biasanya secara singkat mencerminkan alasan kemunculannya:
  • FileNotFoundException(berkas tidak ditemukan)
  • ArithmeticException(pengecualian saat melakukan operasi matematika)
  • ArrayIndexOutOfBoundsException(jumlah sel array ditentukan melebihi panjangnya). Misalnya, jika Anda mencoba mengeluarkan array sel[23] ke konsol untuk array array dengan panjang 10.
Ada hampir 400 kelas seperti itu di Jawa! Mengapa begitu banyak? Justru untuk memudahkan programmer bekerja dengan mereka. Bayangkan: Anda menulis sebuah program, dan ketika dijalankan, ia memunculkan pengecualian yang terlihat seperti ini:
Exception in thread "main"
Uh-uh :/ Tidak ada yang jelas. Kesalahan macam apa itu dan dari mana asalnya masih belum jelas. Tidak ada informasi yang berguna. Namun berkat keragaman kelas tersebut, pemrogram mendapatkan hal utama untuk dirinya sendiri - jenis kesalahan dan kemungkinan penyebabnya, yang terkandung dalam nama kelas. Lagi pula, ini adalah hal yang sangat berbeda untuk dilihat di konsol:
Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Segera menjadi jelas apa masalahnya dan “arah mana yang harus digali” untuk memecahkan masalah tersebut! Pengecualian, seperti contoh kelas lainnya, adalah objek.

Pengecualian Penangkapan dan Penanganan

Untuk bekerja dengan pengecualian di Java, ada blok kode khusus: try, catchdan finally. Pengecualian: intersepsi dan pemrosesan - 2Kode di mana pemrogram mengharapkan terjadinya pengecualian ditempatkan dalam sebuah blok try. Ini tidak berarti bahwa pengecualian akan terjadi di lokasi ini. Artinya hal itu bisa terjadi di sana, dan programmer menyadarinya. Jenis kesalahan yang Anda harapkan akan diterima ditempatkan di blok catch(“catch”). Di sinilah semua kode yang perlu dieksekusi jika terjadi pengecualian ditempatkan. Berikut ini contohnya:
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {

       System.out.println("Error! File not found!");
   }
}
Kesimpulan:

Ошибка! Файл не найден!
Kami menempatkan kode kami dalam dua blok. Di blok pertama kami memperkirakan kesalahan "File tidak ditemukan" mungkin terjadi. Ini adalah sebuah blok try. Yang kedua, kami memberi tahu program apa yang harus dilakukan jika terjadi kesalahan. Selain itu, ada jenis kesalahan tertentu - FileNotFoundException. Jika kita meneruskan catchkelas pengecualian lain ke dalam tanda kurung, kelas tersebut tidak akan ditangkap.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (ArithmeticException e) {

       System.out.println("Error! File not found!");
   }
}
Kesimpulan:

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Системе не удается найти указанный путь)
Kode di blok catchtidak berfungsi karena kami "mengonfigurasi" blok ini untuk mencegat ArithmeticException, dan kode di blok tersebut trymembuang tipe lain - FileNotFoundException. Kami tidak menulis skrip untuk FileNotFoundException, sehingga program menampilkan informasi di konsol yang ditampilkan secara default untuk FileNotFoundException. Di sini Anda perlu memperhatikan 3 hal. Pertama. Segera setelah pengecualian terjadi pada baris kode mana pun di blok coba, kode setelahnya tidak akan lagi dieksekusi. Eksekusi program akan langsung “melompat” ke blok catch. Misalnya:
public static void main(String[] args) {
   try {
       System.out.println("Divide a number by zero");
       System.out.println(366/0);//this line of code will throw an exception

       System.out.println("This");
       System.out.println("code");
       System.out.println("Not");
       System.out.println("will");
       System.out.println("done!");

   } catch (ArithmeticException e) {

       System.out.println("The program jumped to the catch block!");
       System.out.println("Error! You can't divide by zero!");
   }
}
Kesimpulan:

Делим число на ноль 
Программа перепрыгнула в блок catch! 
Ошибка! Нельзя делить на ноль! 
Pada blok trydi baris kedua, kami mencoba membagi angka dengan 0, yang menghasilkan pengecualian ArithmeticException. Setelah ini, baris 6-10 dari blok trytidak akan lagi dieksekusi. Seperti yang kami katakan, program segera mulai mengeksekusi blok tersebut catch. Kedua. Mungkin ada beberapa blok catch. Jika kode dalam sebuah blok trydapat memunculkan bukan hanya satu, tetapi beberapa jenis pengecualian, Anda dapat menulis blok Anda sendiri untuk masing-masing pengecualian tersebut catch.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       System.out.println(366/0);
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {

       System.out.println("Error! File not found!");

   } catch (ArithmeticException e) {

       System.out.println("Error! Division by 0!");

   }
}
Dalam contoh ini kami menulis dua blok catch. Jika, tryterjadi pada blok tersebut FileNotFoundException, blok pertama akan dieksekusi catch. Jika terjadi ArithmeticException, yang kedua akan dieksekusi. Anda dapat menulis setidaknya 50 blok catch, tetapi tentu saja lebih baik tidak menulis kode yang dapat menimbulkan 50 jenis kesalahan yang berbeda :) Ketiga. Bagaimana Anda tahu pengecualian apa yang mungkin diberikan oleh kode Anda? Ya, tentu saja Anda bisa menebaknya, tetapi tidak mungkin mengingat semuanya. Oleh karena itu, kompiler Java mengetahui tentang pengecualian yang paling umum dan mengetahui dalam situasi apa pengecualian tersebut dapat terjadi. Misalnya, jika Anda menulis kode dan kompiler mengetahui bahwa 2 jenis pengecualian mungkin terjadi selama operasinya, kode Anda tidak akan dikompilasi sampai Anda menanganinya. Kita akan melihat contohnya di bawah. Sekarang mengenai penanganan pengecualian. Ada 2 cara untuk mengolahnya. Kami telah bertemu yang pertama - metode ini dapat menangani pengecualian secara independen di blok catch(). Ada opsi kedua - metode ini dapat memunculkan pengecualian pada tumpukan panggilan. Apa artinya? Misalnya, di kelas kita, kita memiliki metode - metode yang sama printFirstString()- yang membaca file dan menampilkan baris pertamanya ke konsol:
public static void printFirstString(String filePath) {

   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Saat ini kode kami tidak dapat dikompilasi karena memiliki pengecualian yang tidak tertangani. Pada baris 1 Anda menunjukkan jalur ke file. Kompiler mengetahui bahwa kode tersebut dapat dengan mudah mengarah ke FileNotFoundException. Pada baris 3 Anda membaca teks dari file. IOExceptionPada proses ini , kesalahan input-output (Input-Output) mudah terjadi . Sekarang kompiler memberi tahu Anda, “Bung, saya tidak akan menyetujui kode ini atau mengkompilasinya sampai Anda memberi tahu saya apa yang harus saya lakukan jika salah satu dari pengecualian ini terjadi. Dan itu pasti bisa terjadi berdasarkan kode yang Anda tulis!” . Tidak ada tujuan, Anda perlu memproses keduanya! Opsi pemrosesan pertama sudah tidak asing lagi bagi kita: kita perlu menempatkan kode kita dalam satu blok trydan menambahkan dua blok catch:
public static void printFirstString(String filePath) {

   try {
       BufferedReader reader = new BufferedReader(new FileReader(filePath));
       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       System.out.println("Error, file not found!");
       e.printStackTrace();
   } catch (IOException e) {
       System.out.println("Error while inputting/outputting data from file!");
       e.printStackTrace();
   }
}
Tapi ini bukan satu-satunya pilihan. Kita dapat menghindari penulisan skrip untuk kesalahan di dalam metode ini, dan cukup melemparkan pengecualian ke atas. Hal ini dilakukan dengan menggunakan kata kunci throws, yang ditulis dalam deklarasi metode:
public static void printFirstString(String filePath) throws FileNotFoundException, IOException {
   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Setelah kata tersebut, throwskami mencantumkan, dipisahkan dengan koma, semua jenis pengecualian yang dapat diberikan metode ini selama operasi. Mengapa hal ini dilakukan? Sekarang, jika seseorang dalam program ingin memanggil metode tersebut printFirstString(), dia harus mengimplementasikan penanganan pengecualian sendiri. Misalnya, di bagian lain program, salah satu kolega Anda menulis sebuah metode yang memanggil metode Anda printFirstString():
public static void yourColleagueMethod() {

   //...your colleague's method does something

   //...and at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
Kesalahan, kode tidak dapat dikompilasi! printFirstString()Kami tidak menulis skrip penanganan kesalahan dalam metode ini . Oleh karena itu, tugas berada di pundak mereka yang akan menggunakan metode ini. Artinya, metode ini yourColleagueMethod()sekarang menghadapi 2 opsi yang sama: metode tersebut harus memproses kedua pengecualian yang “terbang” ke sana menggunakan try-catch, atau meneruskannya lebih jauh.
public static void yourColleagueMethod() throws FileNotFoundException, IOException {
   //...the method does something

   //...and at one moment calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Eugene\\Desktop\\testFile.txt");
}
Dalam kasus kedua, pemrosesan akan berada di pundak metode berikutnya di tumpukan - metode yang akan memanggil yourColleagueMethod(). Itulah sebabnya mekanisme seperti ini disebut “melempar pengecualian ke atas”, atau “melewati ke atas”. Saat Anda melontarkan pengecualian menggunakan throws, kode akan dikompilasi. Pada saat ini, kompiler sepertinya berkata: “Oke, oke. Kode Anda berisi banyak kemungkinan pengecualian, tetapi saya akan tetap mengkompilasinya. Kami akan kembali ke percakapan ini!” Dan ketika Anda memanggil suatu metode di suatu tempat dalam program yang belum menangani pengecualiannya, kompiler memenuhi janjinya dan mengingatkan Anda lagi tentangnya. Terakhir, kita akan membicarakan tentang blok tersebut finally(maafkan permainan kata-katanya). Ini adalah bagian terakhir dari tiga serangkai penanganan pengecualian try-catch-finally. Keunikannya adalah ia dijalankan dalam skenario operasi program apa pun.
public static void main(String[] args) throws IOException {
   try {
       BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       System.out.println("Error! File not found!");
       e.printStackTrace();
   } finally {
       System.out.println("And here is the finally block!");
   }
}
Dalam contoh ini, kode di dalam blok finallydieksekusi dalam kedua kasus. Jika kode dalam blok trydieksekusi seluruhnya dan tidak memunculkan pengecualian, blok tersebut akan diaktifkan di akhir finally. Jika kode di dalamnya tryterganggu dan program melompat ke blok catch, setelah kode di dalamnya dieksekusi catch, blok tersebut akan tetap dipilih finally. Mengapa itu diperlukan? Tujuan utamanya adalah untuk mengeksekusi bagian kode yang diperlukan; bagian yang harus diselesaikan apapun kondisinya. Misalnya, sering kali ini membebaskan beberapa sumber daya yang digunakan oleh program. Dalam kode kami, kami membuka aliran untuk membaca informasi dari file dan meneruskannya ke file BufferedReader. Perusahaan kita readerperlu ditutup dan sumber daya harus dikosongkan. Hal ini harus dilakukan dalam hal apa pun: tidak masalah apakah program berfungsi seperti yang diharapkan atau memberikan pengecualian. Lebih mudah untuk melakukan ini dalam satu blok finally:
public static void main(String[] args) throws IOException {

   BufferedReader reader = null;
   try {
       reader = new BufferedReader(new FileReader("C:\\Users\\Username\\Desktop\\test.txt"));

       String firstString = reader.readLine();
       System.out.println(firstString);
   } catch (FileNotFoundException e) {
       e.printStackTrace();
   } finally {
       System.out.println("And here is the finally block!");
       if (reader != null) {
           reader.close();
       }
   }
}
Sekarang kami benar-benar yakin bahwa kami telah menjaga sumber daya yang digunakan, apa pun yang terjadi saat program sedang berjalan :) Bukan hanya itu yang perlu Anda ketahui tentang pengecualian. Penanganan kesalahan adalah topik yang sangat penting dalam pemrograman: lebih dari satu artikel dikhususkan untuk itu. Pada pelajaran berikutnya kita akan mempelajari jenis pengecualian apa saja yang ada dan cara membuat pengecualian Anda sendiri :) Sampai jumpa!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION