Java - İstisnalar

İstisna (veya istisnai olay), bir programın yürütülmesi sırasında ortaya çıkan bir sorundur. Ne zamanException programın normal akışı bozulur ve program / Uygulama anormal şekilde sona erer, ki bu tavsiye edilmez, bu nedenle bu istisnalar ele alınmalıdır.

Pek çok farklı nedenden dolayı bir istisna meydana gelebilir. Aşağıda bir istisnanın meydana geldiği bazı senaryolar verilmiştir.

  • Bir kullanıcı geçersiz bir veri girdi.

  • Açılması gereken bir dosya bulunamıyor.

  • İletişimin ortasında bir ağ bağlantısı kesildi veya JVM'nin belleği doldu.

Bu istisnalardan bazıları kullanıcı hatasından, diğerleri programcı hatasından ve diğerleri bir şekilde başarısız olan fiziksel kaynaklardan kaynaklanır.

Bunlara dayanarak, üç istisna kategorimiz var. Java'da istisna işlemenin nasıl çalıştığını bilmek için onları anlamanız gerekir.

  • Checked exceptions- Kontrol edilen istisna, derleme zamanında derleyici tarafından kontrol edilen (bildirilen) bir istisnadır, bunlara ayrıca derleme zamanı istisnaları da denir. Bu istisnalar basitçe göz ardı edilemez, programcı bu istisnalara dikkat etmelidir (ele almalıdır).

Örneğin, kullanıyorsanız FileReaderOluşturucusunda belirtilen dosya yoksa, bir FileNotFoundException oluşur ve derleyici programcıdan istisnayı işlemesini ister.

Misal

import java.io.File;
import java.io.FileReader;

public class FilenotFound_Demo {

   public static void main(String args[]) {		
      File file = new File("E://file.txt");
      FileReader fr = new FileReader(file); 
   }
}

Yukarıdaki programı derlemeye çalışırsanız, aşağıdaki istisnaları alırsınız.

Çıktı

C:\>javac FilenotFound_Demo.java
FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
      FileReader fr = new FileReader(file);
                      ^
1 error

Note - Yöntemlerden beri read() ve close() of FileReader sınıfı IOException oluşturursa, derleyicinin FileNotFoundException ile birlikte IOException'ı işlemek için bildirimde bulunduğunu gözlemleyebilirsiniz.

  • Unchecked exceptions- Denetlenmemiş bir istisna, yürütme sırasında meydana gelen bir istisnadır. Bunlar aynı zamandaRuntime Exceptions. Bunlar, mantık hataları veya bir API'nin uygunsuz kullanımı gibi programlama hatalarını içerir. Çalışma zamanı istisnaları, derleme sırasında göz ardı edilir.

Eğer programda büyüklüğü 5 dizisi beyan ve 6 aramaya çalışıyorum varsa Örneğin, inci dizinin elemanını daha sonra bir ArrayIndexOutOfBoundsExceptionexception oluşur.

Misal

public class Unchecked_Demo {
   
   public static void main(String args[]) {
      int num[] = {1, 2, 3, 4};
      System.out.println(num[5]);
   }
}

Yukarıdaki programı derler ve çalıştırırsanız, aşağıdaki istisnayı alırsınız.

Çıktı

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
	at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)
  • Errors- Bunlar hiçbir şekilde istisna değil, kullanıcının veya programcının kontrolü dışında ortaya çıkan sorunlardır. Bir hata hakkında nadiren herhangi bir şey yapabileceğiniz için, kodunuzda hatalar genellikle yok sayılır. Örneğin, bir yığın taşması meydana gelirse, bir hata ortaya çıkacaktır. Derleme sırasında da dikkate alınmazlar.

İstisna Hiyerarşisi

Tüm istisna sınıfları, java.lang.Exception sınıfının alt türleridir. İstisna sınıfı, Throwable sınıfının bir alt sınıfıdır. İstisna sınıfı dışında, Throwable sınıfından türetilen Error adlı başka bir alt sınıf vardır.

Hatalar, ciddi arızalar durumunda ortaya çıkan anormal durumlardır, bunlar Java programları tarafından ele alınmaz. Çalışma zamanı ortamı tarafından oluşturulan hataları belirtmek için hatalar üretilir. Örnek: JVM bellek yetersiz. Normalde programlar hatalardan kurtulamaz.

Exception sınıfının iki ana alt sınıfı vardır: IOException sınıfı ve RuntimeException Sınıfı.

Aşağıda, Java'nın Yerleşik İstisnalarının en yaygın olarak kontrol edilen ve kontrol edilmeyen bir listesi bulunmaktadır .

İstisna Yöntemleri

Throwable sınıfında bulunan önemli yöntemlerin listesi aşağıdadır.

Sr.No. Yöntem ve Açıklama
1

public String getMessage()

Oluşan istisna hakkında ayrıntılı bir mesaj verir. Bu mesaj Throwable yapıcısında başlatılır.

2

public Throwable getCause()

Throwable nesne tarafından temsil edildiği şekliyle istisnanın nedenini döndürür.

3

public String toString()

GetMessage () sonucuyla birleştirilen sınıfın adını döndürür.

4

public void printStackTrace()

ToString () sonucunu yığın izlemeyle birlikte System.err, hata çıktı akışı olarak yazdırır.

5

public StackTraceElement [] getStackTrace()

Yığın izlemesindeki her bir öğeyi içeren bir dizi döndürür. 0 dizinindeki öğe, çağrı yığınının üstünü temsil eder ve dizideki son öğe, çağrı yığınının altındaki yöntemi temsil eder.

6

public Throwable fillInStackTrace()

Bu Throwable nesnesinin yığın izlemesini mevcut yığın izlemesiyle doldurur ve yığın izlemedeki önceki bilgilere ekleme yapar.

İstisnaları Yakalama

Bir yöntem, bir try ve catchanahtar kelimeler. Bir istisna oluşturabilecek kodun etrafına bir dene / yakala bloğu yerleştirilir. Bir dene / yakala bloğundaki kod korumalı kod olarak adlandırılır ve dene / yakala kullanımının sözdizimi aşağıdaki gibi görünür -

Sözdizimi

try {
   // Protected code
} catch (ExceptionName e1) {
   // Catch block
}

İstisnalara açık olan kod, try bloğuna yerleştirilir. Bir istisna meydana geldiğinde, meydana gelen istisna, kendisiyle ilişkilendirilmiş catch bloğu tarafından ele alınır. Her try bloğunun hemen ardından bir catch bloğu veya nihayet bloğu gelmelidir.

Bir catch deyimi, yakalamaya çalıştığınız istisna türünü bildirmeyi içerir. Korumalı kodda bir istisna meydana gelirse, denemeyi izleyen catch bloğu (veya blokları) kontrol edilir. Oluşan istisna türü bir catch bloğunda listelenirse, istisna, bir bağımsız değişken bir yöntem parametresine iletildiği gibi catch bloğuna iletilir.

Misal

Aşağıdaki 2 elemanlı bir dizidir. Daha sonra kod , bir istisna atan dizinin 3. öğesine erişmeye çalışır .

// File Name : ExcepTest.java
import java.io.*;

public class ExcepTest {

   public static void main(String args[]) {
      try {
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      } catch (ArrayIndexOutOfBoundsException e) {
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
}

Bu, aşağıdaki sonucu verecektir -

Çıktı

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block

Çoklu Yakalama Blokları

Bir try bloğunun ardından birden fazla catch bloğu gelebilir. Birden çok yakalama bloğunun sözdizimi aşağıdaki gibidir -

Sözdizimi

try {
   // Protected code
} catch (ExceptionType1 e1) {
   // Catch block
} catch (ExceptionType2 e2) {
   // Catch block
} catch (ExceptionType3 e3) {
   // Catch block
}

Önceki ifadeler üç catch bloğunu gösterir, ancak tek bir denemeden sonra bunlardan istediğiniz kadarına sahip olabilirsiniz. Korunan kodda bir istisna oluşursa, istisna listedeki ilk catch bloğuna atılır. Atılan istisnanın veri türü ExceptionType1 ile eşleşirse, orada yakalanır. Aksi takdirde, istisna ikinci catch ifadesine aktarılır. Bu, istisna yakalanana veya tüm yakalamalardan geçene kadar devam eder, bu durumda geçerli yöntem yürütmeyi durdurur ve istisna, çağrı yığınındaki önceki yönteme atılır.

Misal

Birden çok dene / yakala ifadesinin nasıl kullanılacağını gösteren kod bölümü.

try {
   file = new FileInputStream(fileName);
   x = (byte) file.read();
} catch (IOException i) {
   i.printStackTrace();
   return -1;
} catch (FileNotFoundException f) // Not valid! {
   f.printStackTrace();
   return -1;
}

Birden Fazla İstisna Türünü Yakalama

Java 7'den beri, tek bir yakalama bloğu kullanarak birden fazla istisnayı idare edebilirsiniz, bu özellik kodu basitleştirir. İşte bunu nasıl yapardınız -

catch (IOException|FileNotFoundException ex) {
   logger.log(ex);
   throw ex;

Fırlatma / Atma Anahtar Kelimeleri

Bir yöntem kontrol edilen bir istisnayı işlemezse, yöntemin bunu kullanarak bildirmesi gerekir. throwsanahtar kelime. Throws anahtar sözcüğü bir yöntemin imzasının sonunda görünür.

Kullanarak, yeni başlatılmış bir istisna veya yeni yakaladığınız bir istisna atabilirsiniz. throw anahtar kelime.

Fırlatma ve anahtar sözcük atma arasındaki farkı anlamaya çalışın, fırlatmalar , kontrol edilen bir istisnanın işlenmesini ertelemek için kullanılır ve fırlatma , bir istisnayı açıkça çağırmak için kullanılır.

Aşağıdaki yöntem, bir RemoteException oluşturduğunu bildirir -

Misal

import java.io.*;
public class className {

   public void deposit(double amount) throws RemoteException {
      // Method implementation
      throw new RemoteException();
   }
   // Remainder of class definition
}

Bir yöntem, birden fazla istisna attığını bildirebilir, bu durumda istisnalar virgülle ayrılmış bir listede bildirilir. Örneğin, aşağıdaki yöntem bir RemoteException ve InsufficientFundsException attığını bildirir -

Misal

import java.io.*;
public class className {

   public void withdraw(double amount) throws RemoteException, 
      InsufficientFundsException {
      // Method implementation
   }
   // Remainder of class definition
}

Nihayet Blok

Nihayet bloğu, bir try bloğunu veya bir catch bloğunu takip eder. Nihayetinde bir kod bloğu, bir İstisnanın ortaya çıkmasına bakılmaksızın her zaman yürütülür.

Nihayet bloğunun kullanılması, korumalı kodda ne olursa olsun, yürütmek istediğiniz herhangi bir temizleme türü ifadesini çalıştırmanıza olanak tanır.

Catch bloklarının sonunda bir nihayet bloğu görünür ve aşağıdaki sözdizimine sahiptir -

Sözdizimi

try {
   // Protected code
} catch (ExceptionType1 e1) {
   // Catch block
} catch (ExceptionType2 e2) {
   // Catch block
} catch (ExceptionType3 e3) {
   // Catch block
}finally {
   // The finally block always executes.
}

Misal

public class ExcepTest {

   public static void main(String args[]) {
      int a[] = new int[2];
      try {
         System.out.println("Access element three :" + a[3]);
      } catch (ArrayIndexOutOfBoundsException e) {
         System.out.println("Exception thrown  :" + e);
      }finally {
         a[0] = 6;
         System.out.println("First element value: " + a[0]);
         System.out.println("The finally statement is executed");
      }
   }
}

Bu, aşağıdaki sonucu verecektir -

Çıktı

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed

Aşağıdakilere dikkat edin -

  • Bir try ifadesi olmadan catch cümlesi var olamaz.

  • Bir dene / yakala bloğu mevcut olduğunda nihayet cümleciklerine sahip olmak zorunlu değildir.

  • Try bloğu, catch yan tümcesi veya nihayet yan tümcesi olmadan mevcut olamaz.

  • Try, catch, nihayet blokları arasında herhangi bir kod bulunamaz.

Kaynaklarla deneme

Genel olarak, akışlar, bağlantılar vb. Gibi kaynakları kullandığımızda, bunları nihayet blok kullanarak açıkça kapatmamız gerekir. Aşağıdaki programda, kullanarak bir dosyadan veri okuyoruzFileReader ve nihayet bloğu kullanarak kapatıyoruz.

Misal

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]) {
      FileReader fr = null;		
      try {
         File file = new File("file.txt");
         fr = new FileReader(file); char [] a = new char[50];
         fr.read(a);   // reads the content to the array
         for(char c : a)
         System.out.print(c);   // prints the characters one by one
      } catch (IOException e) {
         e.printStackTrace();
      }finally {
         try {
            fr.close();
         } catch (IOException ex) {		
            ex.printStackTrace();
         }
      }
   }
}

try-with-resourcesolarak da anılır automatic resource management, Java 7'de sunulan, try catch bloğu içinde kullanılan kaynakları otomatik olarak kapatan yeni bir istisna işleme mekanizmasıdır.

Bu ifadeyi kullanmak için, gerekli kaynakları parantez içinde bildirmeniz yeterlidir ve oluşturulan kaynak bloğun sonunda otomatik olarak kapatılacaktır. Aşağıda, kaynakları ile deneme ifadesinin sözdizimi verilmiştir.

Sözdizimi

try(FileReader fr = new FileReader("file path")) {
   // use the resource
   } catch () {
      // body of catch 
   }
}

Aşağıda, kaynakları dene deyimini kullanarak bir dosyadaki verileri okuyan program verilmiştir.

Misal

import java.io.FileReader;
import java.io.IOException;

public class Try_withDemo {

   public static void main(String args[]) {
      try(FileReader fr = new FileReader("E://file.txt")) {
         char [] a = new char[50];
         fr.read(a);   // reads the contentto the array
         for(char c : a)
         System.out.print(c);   // prints the characters one by one
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

Kaynaklarla deneme ifadesiyle çalışırken aşağıdaki noktalar akılda tutulmalıdır.

  • Kaynakları dene deyimi olan bir sınıfı kullanmak için uygulaması gerekir AutoCloseable arayüz ve close() yöntemi çalışma zamanında otomatik olarak çağrılır.

  • Kaynakları dene deyiminde birden fazla sınıf bildirebilirsiniz.

  • Kaynakları dene deyiminin try bloğunda birden çok sınıf bildirirken, bu sınıflar ters sırada kapatılır.

  • Parantez içindeki kaynakların bildirimi dışında her şey bir try bloğunun normal dene / yakala bloğuyla aynıdır.

  • Try'de bildirilen kaynak, try bloğunun başlamasından hemen önce somutlaştırılır.

  • Try bloğunda bildirilen kaynak örtük olarak nihai olarak bildirilir.

Kullanıcı Tanımlı İstisnalar

Java'da kendi istisnalarınızı oluşturabilirsiniz. Kendi istisna sınıflarınızı yazarken aşağıdaki noktaları aklınızda bulundurun -

  • Tüm istisnalar, Atılabilir bir çocuk olmalıdır.

  • Tutamaç veya Bildirme Kuralı tarafından otomatik olarak zorlanan bir kontrol edilmiş istisna yazmak istiyorsanız, Exception sınıfını genişletmeniz gerekir.

  • Bir çalışma zamanı istisnası yazmak istiyorsanız, RuntimeException sınıfını genişletmeniz gerekir.

Kendi Exception sınıfımızı aşağıdaki gibi tanımlayabiliriz -

class MyException extends Exception {
}

Önceden tanımlanmış olanı genişletmeniz yeterlidir. Exceptionkendi İstisnanızı oluşturmak için sınıf. Bunlar istisnai durumlar olarak değerlendirilir. AşağıdakiInsufficientFundsExceptionsınıfı, Exception sınıfını genişleten ve onu kontrol edilen bir istisna haline getiren kullanıcı tanımlı bir istisnadır. Bir istisna sınıfı, kullanışlı alanlar ve yöntemler içeren diğer sınıflar gibidir.

Misal

// File Name InsufficientFundsException.java
import java.io.*;

public class InsufficientFundsException extends Exception {
   private double amount;
   
   public InsufficientFundsException(double amount) {
      this.amount = amount;
   }
   
   public double getAmount() {
      return amount;
   }
}

Kullanıcı tanımlı istisnamızı kullanmayı göstermek için, aşağıdaki CheckingAccount sınıfı bir InsufficientFundsException oluşturan bir withdraw () yöntemini içerir.

// File Name CheckingAccount.java
import java.io.*;

public class CheckingAccount {
   private double balance;
   private int number;
   
   public CheckingAccount(int number) {
      this.number = number;
   }
   
   public void deposit(double amount) {
      balance += amount;
   }
   
   public void withdraw(double amount) throws InsufficientFundsException {
      if(amount <= balance) {
         balance -= amount;
      }else {
         double needs = amount - balance;
         throw new InsufficientFundsException(needs);
      }
   }
   
   public double getBalance() {
      return balance;
   }
   
   public int getNumber() {
      return number;
   }
}

Aşağıdaki BankDemo programı, CheckingAccount'un deposit () ve withdraw () yöntemlerini çağırmayı gösterir.

// File Name BankDemo.java
public class BankDemo {

   public static void main(String [] args) {
      CheckingAccount c = new CheckingAccount(101);
      System.out.println("Depositing $500...");
      c.deposit(500.00);
      
      try {
         System.out.println("\nWithdrawing $100...");
         c.withdraw(100.00);
         System.out.println("\nWithdrawing $600...");
         c.withdraw(600.00);
      } catch (InsufficientFundsException e) {
         System.out.println("Sorry, but you are short $" + e.getAmount());
         e.printStackTrace();
      }
   }
}

Yukarıdaki üç dosyanın tümünü derleyin ve BankDemo'yu çalıştırın. Bu, aşağıdaki sonucu verecektir -

Çıktı

Depositing $500...

Withdrawing $100...

Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
         at CheckingAccount.withdraw(CheckingAccount.java:25)
         at BankDemo.main(BankDemo.java:13)

Yaygın İstisnalar

Java'da, İstisnalar ve Hatalar olmak üzere iki kategori tanımlamak mümkündür.

  • JVM Exceptions- Bunlar, özel olarak veya mantıksal olarak JVM tarafından atılan istisnalar / hatalardır. Örnekler: NullPointerException, ArrayIndexOutOfBoundsException, ClassCastException.

  • Programmatic Exceptions- Bu istisnalar, uygulama veya API programcıları tarafından açıkça atılır. Örnekler: IllegalArgumentException, IllegalStateException.