CodeGym /Java Blogu /Rastgele /İstisnalar: yakalama ve taşıma
John Squirrels
Seviye
San Francisco

İstisnalar: yakalama ve taşıma

grupta yayınlandı
MERHABA! Bundan bahsetmekten nefret ediyorum ama bir programcının işinin büyük bir kısmı hatalarla uğraşmaktır. Çoğu zaman, kendi. Meğer hata yapmayan insan yokmuş. Ve böyle programlar da yok. İstisnalar: yakalama ve taşıma - 1 Elbette bir hatayla uğraşırken asıl mesele sebebini anlamaktır.. Ve pek çok şey bir programda hatalara neden olabilir. Bir noktada, Java'nın yaratıcıları kendilerine en olası programlama hatalarında ne yapılması gerektiğini sordular. Onlardan tamamen kaçınmak gerçekçi değildir, programcılar hayal bile edemeyeceğiniz şeyler yazabilirler. :) Öyleyse, dile hatalarla çalışmak için bir mekanizma vermemiz gerekiyor. Başka bir deyişle, programınızda bir hata varsa, bundan sonra ne yapacağınız için bir tür komut dosyasına ihtiyacınız vardır. Bir program bir hata oluştuğunda tam olarak ne yapmalıdır? Bugün bu mekanizma ile tanışacağız. Buna " Java'daki istisnalar " denir .

İstisna nedir?

İstisna, bir program çalışırken meydana gelen istisnai, planlanmamış bir durumdur. Birçok istisna var. Örneğin, bir dosyadan metin okuyan ve ilk satırı görüntüleyen bir kod yazdınız.

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);
   }
}
Ama ya böyle bir dosya yoksa! Program bir istisna oluşturacaktır: FileNotFoundException. Çıktı: "main" dizisindeki istisna java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Sistem belirtilen yolu bulamıyor) Java'da her istisna ayrı bir sınıf tarafından temsil edilir. ThrowableTüm bu istisna sınıfları, ortak bir "atadan" - ana sınıftan türemiştir . Bir istisna sınıfının adı genellikle istisnanın neden oluştuğunu kısaca yansıtır:
  • FileNotFoundException(dosya bulunamadı)

  • ArithmeticException(matematiksel bir işlem gerçekleştirilirken bir istisna oluştu)

  • ArrayIndexOutOfBoundsException(dizin, dizinin sınırlarının ötesindedir). Örneğin, yalnızca 10 öğe içeren bir dizinin 23. konumunu görüntülemeye çalışırsanız bu istisna oluşur.
Toplamda, Java'da bu türden neredeyse 400 sınıf vardır! Neden bu kadar çok? Programcıların birlikte çalışmasını daha uygun hale getirmek için. Şunu hayal edin: Bir program yazıyorsunuz ve çalışırken şuna benzer bir istisna oluşturuyor:

Exception in thread "main"
Uhhhh. :/ Pek yardımcı olmuyor. Hatanın ne anlama geldiği veya nereden geldiği belli değil. Burada yararlı bilgi yok. Ancak Java'daki çok çeşitli istisna sınıfları, programcıya en önemli olanı verir: hatanın türü ve olası nedeni (sınıf adına gömülü). Görmek çok başka bir şey

Exception in thread "main" java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (The system cannot find the specified path)
Sorunun ne olabileceği ve sorunu çözmek için nereden kazmaya başlayacağınız hemen anlaşılır! İstisnalar, herhangi bir sınıfın örnekleri gibi nesnelerdir.

İstisnaları yakalama ve işleme

Java, istisnalarla çalışmak için özel kod bloklarına sahiptir: try, catchve finally. İstisnalar: yakalama ve taşıma - 2 Programcının bir istisna olabileceğine inandığı kod bloğa yerleştirilir try. Bu, burada bir istisna olacağı anlamına gelmez. Burada meydana gelebileceği anlamına gelir ve programcı bu olasılığın farkındadır. Oluşmasını beklediğiniz hata türü bloğa yerleştirilir catch. Bu aynı zamanda bir istisna meydana geldiğinde yürütülmesi gereken tüm kodu içerir. İşte bir örnek:

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!");
   }
}
Çıktı: Hata! Dosya bulunamadı! Kodumuzu iki bloğa koyuyoruz. İlk blokta "Dosya bulunamadı" hatası oluşabileceğini tahmin ediyoruz. Bu tryblok. İkinci adımda programa bir hata oluştuğunda ne yapacağını söylüyoruz. Ve belirli hata türü: FileNotFoundException. catchBloğun parantezlerine farklı bir istisna sınıfı koyarsak FileNotFoundExceptionyakalanmaz.

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!");
   }
}
Çıktı: "main" dizisindeki istisna java.io.FileNotFoundException: C:\Users\Username\Desktop\test.txt (Sistem belirtilen yolu bulamıyor) Bloktaki kod catchçalışmadı, çünkü "yapılandırdık" bu bloğu yakalamak için ArithmeticExceptionve bloktaki kod tryfarklı bir tür attı: FileNotFoundException. İşlemek için herhangi bir kod yazmadık FileNotFoundException, bu nedenle program için varsayılan bilgileri görüntüler FileNotFoundException. Burada üç şeye dikkat etmeniz gerekiyor. Bir numara. Bloktaki bir satırda bir istisna oluştuğunda try, takip eden kod yürütülmeyecektir. Programın yürütülmesi hemen bloğa "atlar" catch. Örneğin:

public static void main(String[] args) {
   try {
       System.out.println("Divide 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("will not");
       System.out.println("be");
       System.out.println("executed!");

   } catch (ArithmeticException e) {

       System.out.println("The program jumped to the catch block!");
       System.out.println("Error! You can't divide by zero!");
   }
}
Çıktı: Sıfıra böl Program catch bloğuna atladı! Hata! Sıfıra bölemezsiniz! Bloğun ikinci satırında try, 0'a bölmeye çalışırız, sonuç olarak ArithmeticException. Sonuç olarak, bloğun 3-9 satırları tryyürütülmez. Dediğimiz gibi program hemen catchbloğu çalıştırmaya başlar. İki numaralı. Birkaç blok olabilir catch. Bloktaki kod bir değil, birkaç farklı türde istisna atıyorsa, her biri için trybir blok yazabilirsiniz .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!");
      
   }
}
Bu örnekte iki blok yazdık catch. FileNotFoundExceptionBlokta a oluşursa try, ilk catchblok yürütülür. Bir ArithmeticExceptionoluşursa, ikinci blok yürütülür. catchİsterseniz 50 blok yazabilirsiniz . Elbette, 50 farklı türde istisna oluşturabilecek kod yazmamak daha iyidir. :) Üçüncüsü. Kodunuzun hangi istisnaları atabileceğini nasıl bilebilirsiniz? Pekala, bazılarını tahmin edebiliyor olabilirsiniz ama her şeyi kafanızda tutmanız imkansız. Java derleyicisi bu nedenle en yaygın istisnaları ve bunların oluşabileceği durumları bilir. Örneğin, derleyicinin iki tür istisna oluşturabileceğini bildiği bir kod yazarsanız, siz bunları işleyene kadar kodunuz derlenmez. Bunun örneklerini aşağıda göreceğiz. Şimdi istisna işleme hakkında birkaç kelime. İstisnaları işlemenin 2 yolu vardır. İlkiyle zaten karşılaştık: yöntem bir blokta istisnanın kendisini işleyebilir catch(). İkinci bir seçenek daha vardır: yöntem, istisnayı çağrı yığınının yukarısına yeniden fırlatabilir. Bu ne anlama gelir? Örneğin, printFirstString()bir dosyayı okuyan ve ilk satırını görüntüleyen, aynı yönteme sahip bir sınıfımız var:

public static void printFirstString(String filePath) {

   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Şu anda, işlenmemiş istisnalar içerdiğinden kodumuz derlenmiyor. 1. satırda, dosyanın yolunu belirtirsiniz. Derleyici, böyle bir kodun kolayca bir FileNotFoundException. 3. satırda, dosyadaki metni okursunuz. Bu işlem kolayca bir (giriş/çıkış hatası) ile sonuçlanabilir IOException. Şimdi derleyici size diyor ki, "Dostum, bu kodu onaylamayacağım ve sen bana bu istisnalardan biri olursa ne yapmam gerektiğini söyleyene kadar derlemeyeceğim. Ve yazdığın koda göre kesinlikle gerçekleşebilirler. !" Bunu aşmanın bir yolu yok: ikisini de halletmeniz gerekiyor! İlk istisna işleme yöntemini zaten biliyoruz: kodumuzu bir bloğa koymamız tryve iki catchblok eklememiz gerekiyor:

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("File input/output error!");
       e.printStackTrace();
   }
}
Ancak bu tek seçenek değil. Yöntemin içine hata işleme kodu yazmak yerine istisnayı daha yükseğe fırlatabiliriz. throwsBu, yöntem bildirimindeki anahtar sözcük kullanılarak yapılır :

public static void printFirstString(String filePath) throws FileNotFoundException, IOException {
   BufferedReader reader = new BufferedReader(new FileReader(filePath));
   String firstString = reader.readLine();
   System.out.println(firstString);
}
Anahtar kelimeden sonra throws, yöntemin oluşturabileceği tüm istisna türlerinin virgülle ayrılmış bir listesini belirtiriz. Neden? printFirstString()Şimdi, birisi programdaki yöntemi çağırmak isterse , o (siz değil) istisna işlemeyi uygulamak zorunda kalacak. Örneğin, programın herhangi bir yerinde iş arkadaşlarınızdan birinin sizin printFirstString()yönteminizi çağıran bir yöntem yazdığını varsayalım:

public static void yourColleagueMethod() {

   // Your colleague's method does something

   //...and then calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Henry\\Desktop\\testFile.txt");
}
Bir hata alıyoruz! Bu kod derlenmeyecek! Yöntemde istisna işleme kodu yazmadık printFirstString(). Sonuç olarak bu görev artık yöntemi kullananların omuzlarına düşüyor. Başka bir deyişle, yöntem artık aynı 2 seçeneğe sahiptir: ya her iki istisnayı da işlemek için methodWrittenByYourColleague()bir blok kullanmalı ya da onları yeniden atmalıdır.try-catch

public static void yourColleagueMethod() throws FileNotFoundException, IOException {
   // The method does something

   //...and then calls your printFirstString() method with the file it needs
   printFirstString("C:\\Users\\Henry\\Desktop\\testFile.txt");
}
İkinci durumda, çağrı yığınındaki bir sonraki yöntem - çağıran methodWrittenByYourColleague()- istisnaları işlemek zorunda kalacak. Bu yüzden buna "istisnayı atmak veya geçmek" diyoruz. Anahtar kelimeyi kullanarak yukarı doğru istisnalar atarsanız throws, kodunuz derlenir. Bu noktada, derleyici "Tamam, tamam. Kodunuz bir dizi potansiyel istisna içeriyor, ama ben onu derleyeceğim. Ama bu konuşmaya geri döneceğiz!" Ve işlenmemiş istisnaları olan herhangi bir yöntemi çağırdığınızda, derleyici sözünü yerine getirir ve size onları tekrar hatırlatır. Son olarak blok hakkında konuşacağız finally(kelime oyunu için özür dilerim). Bu, triumvirate işleme istisnasının son kısmıdır try-catch-finally..

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's the finally block!");
   }
}
Bu örnekte, bloğun içindeki kod finallyher iki durumda da yürütülecektir. Bloktaki kod tryherhangi bir istisna atmadan tam olarak çalıştırılırsa, finallyblok sonunda çalışacaktır. Bloğun içindeki kod trybir istisna tarafından kesintiye uğrarsa ve program bloğa atlarsa catch, finallyblok yine de bloğun içindeki koddan sonra çalışır catch. Bu neden gerekli? Ana amacı, zorunlu kodu yürütmektir: koşullar ne olursa olsun gerçekleştirilmesi gereken kod. Örneğin, genellikle program tarafından kullanılan bazı kaynakları serbest bırakır. Kodumuzda dosyadan bilgi okumak ve nesneye iletmek için bir akış açıyoruz BufferedReader. Okuyucumuzu kapatmalı ve kaynakları serbest bırakmalıyız. Bu, ne olursa olsun, program olması gerektiği gibi çalıştığında ve bir istisna oluşturduğunda yapılmalıdır. Blok finally, bunu yapmak için çok uygun bir yerdir:

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's the finally block!");
       if (reader != null) {
           reader.close();
       }
   }
}
Artık program çalışırken ne olursa olsun kaynaklarla ilgileneceğimizden eminiz. :) İstisnalar hakkında bilmeniz gereken tek şey bu değil. Hata işleme, programlamada çok önemli bir konudur. Birçok makale buna ayrılmıştır. Bir sonraki derste, ne tür istisnalar olduğunu ve kendi istisnalarınızı nasıl oluşturacağınızı öğreneceğiz. :) Sonra görüşürüz!
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION