1. İstisna türleri

Tüm istisnalar, aslında birbirini miras alan sınıflar olan 4 türe ayrılır.

Throwablesınıf

Tüm istisnalar için temel sınıf, sınıftır Throwable. Sınıf, Throwablegeçerli çağrı yığınını (geçerli yöntemin yığın izlemesi) bir diziye yazan kodu içerir. Yığın izlemenin ne olduğunu biraz sonra öğreneceğiz.

Fırlatma operatörü , yalnızca sınıftan türetilen bir nesneyi kabul edebilir Throwable. Ve teorik olarak şöyle bir kod yazabilseniz de throw new Throwable();, bunu genellikle kimse yapmaz. Sınıfın temel amacı Throwable, tüm istisnalar için tek bir üst sınıfa sahip olmaktır.

Errorsınıf

Bir sonraki istisna sınıfı Error, sınıfı doğrudan miras alan sınıftır Throwable. Java makinesi, ciddi sorunlar meydana geldiğindeError sınıfın (ve soyundan gelenlerin) nesnelerini oluşturur . Örneğin, bir donanım arızası, yetersiz bellek vb.

Genellikle bir programcı olarak, programda böyle bir hatanın (atılması gereken türden) meydana geldiği bir durumda yapabileceğiniz hiçbir şey yoktur : bu hatalar çok ciddidir. ErrorYapabileceğiniz tek şey, kullanıcıya programın kilitlendiğini bildirmek ve/veya hatayla ilgili bilinen tüm bilgileri program günlüğüne yazmaktır.

Exceptionsınıf

Exceptionve sınıfları RuntimeException, birçok yöntemin çalışmasında meydana gelen yaygın hatalar içindir. Fırlatılan her istisnanın amacı , onu düzgün bir şekilde nasıl ele alacağını bilen bir blok tarafından yakalanmaktır .catch

Bir yöntem herhangi bir nedenle işini tamamlayamadığında, uygun türde bir istisna atarak çağıran yönteme derhal bildirimde bulunmalıdır.

Başka bir deyişle, bir değişken eşittir ise null, yöntem bir atar NullPointerException. Yönteme yanlış bağımsız değişkenler iletildiyse, bir InvalidArgumentException. Yöntem yanlışlıkla sıfıra bölerse, bir ArithmeticException.

RuntimeExceptionsınıf

RuntimeExceptionsnin bir alt kümesidir Exceptions. RuntimeExceptionBunun sıradan istisnaların ( ) hafif bir versiyonu olduğunu bile söyleyebiliriz Exception- bu tür istisnalara daha az gereksinim ve kısıtlama uygulanır.

Exceptionile arasındaki farkı daha sonra öğreneceksiniz RuntimeException.


2. Throws: kontrol edilen istisnalar

Tüm Java istisnaları 2 kategoriye ayrılır: işaretli ve işaretsiz .

RuntimeExceptionveya öğesini devralan tüm istisnalar, denetlenmeyen istisnalarError olarak kabul edilir . Diğer tüm istisnalar kontrol edilir .

Önemli!

Denetlenen istisnaların tanıtılmasından yirmi yıl sonra, hemen hemen her Java programcısı bunun bir hata olduğunu düşünür. Popüler modern çerçevelerde, tüm istisnaların %95'i denetlenmez. Java'yı neredeyse birebir kopyalayan C# dili, kontrol edilen istisnaları eklemedi .

Kontrol edilen ve kontrol edilmeyen istisnalar arasındaki temel fark nedir ?

Kontrol edilen istisnalara uygulanan ek gereksinimler vardır . Kabaca söylemek gerekirse bunlar:

Gereksinim 1

Bir yöntem kontrol edilen bir istisna atarsa , imzasında istisna türünü belirtmelidir . Bu şekilde, onu çağıran her yöntem, bu "anlamlı istisnanın" kendi içinde oluşabileceğinin farkındadır.

Anahtar kelimeden sonra yöntem parametrelerinden sonra işaretli istisnaları belirtin ( yanlışlıkla anahtar kelimeyi kullanmayın ). Şunun gibi görünüyor:throwsthrow

type method (parameters) throws exception

Örnek:

işaretli istisna denetlenmeyen istisna
public void calculate(int n) throws Exception
{
   if (n == 0)
      throw new Exception("n is null!");
}
public void calculate(n)
{
   if (n == 0)
      throw new RuntimeException("n is null!");
}

Sağdaki örnekte, kodumuz denetlenmeyen bir istisna oluşturuyor; ek bir işlem gerekmiyor. Soldaki örnekte, yöntem kontrol edilen bir istisna atar, böylece throwsanahtar kelime, istisna türüyle birlikte yöntem imzasına eklenir.

Bir yöntem birden fazla kontrol edilen istisna atmayı bekliyorsa , bunların tümü throwsanahtar kelimeden sonra virgülle ayrılarak belirtilmelidir . Sıra önemli değil. Örnek:

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");
}

Gereksinim 2

İmzasında istisnaları kontrol eden bir yöntemi çağırırsanız , istisnaları attığı gerçeğini göz ardı edemezsiniz.

catchYa her biri için bloklar ekleyerek ya da bunları yönteminiz için bir throwsyan tümceye ekleyerek tüm bu tür istisnaları yakalamanız gerekir .

Sanki " Bu istisnalar o kadar önemli ki onları yakalamamız gerekiyor. Ve eğer onlarla nasıl başa çıkacağımızı bilmiyorsak, o zaman yöntemimizi çağırabilecek herkese bu tür istisnaların oluşabileceği bildirilmelidir.

Örnek:

İnsanların yaşadığı bir dünya yaratmak için bir yöntem yazdığımızı hayal edin. İlk kişi sayısı bağımsız değişken olarak iletilir. Bu nedenle, çok az kişi varsa istisnalar eklememiz gerekir.

Dünya Yaratmak Not
public void createWorld(int n) throws EmptyWorldException, LonelyWorldException
{
   if (n == 0)
      throw new EmptyWorldException("There are no people!");
   if (n == 1)
      throw new LonelyWorldException ("There aren't enough people!");
   System.out.println("A wonderful world was created. Population: " + n);
}
Yöntem potansiyel olarak iki kontrol edilen istisna atar:

  • EmptyWorldİstisna
  • LonelyWorldİstisna

Bu yöntem çağrısı 3 şekilde ele alınabilir:

1. Herhangi bir istisna yakalamayın

Bu genellikle, yöntem durumu düzgün bir şekilde nasıl ele alacağını bilmediğinde yapılır.

kod Not
public void createPopulatedWorld(int population)
throws EmptyWorldException, LonelyWorldException
{
   createWorld(population);
}
Çağıran yöntem istisnaları yakalamaz ve diğerlerini onlar hakkında bilgilendirmek zorundadır: onları kendi throwsyan tümcesine ekler.

2. İstisnalardan bazılarını yakalayın

Başa çıkabileceğimiz hataları hallederiz. Ama anlamadıklarımızı çağıran metoda atıyoruz. Bunu yapmak için, throws yan tümcesine adlarını eklememiz gerekir:

kod Not
public void createNonEmptyWorld(int population)
throws EmptyWorldException
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
}
Arayan yalnızca bir işaretli istisna yakalar — LonelyWorldException. throwsDiğer istisna, anahtar kelimeden sonra belirtilerek imzasına eklenmelidir.

3. Tüm istisnaları yakalayın

Yöntem, çağıran yönteme istisnalar atmazsa, çağıran yöntem her zaman her şeyin yolunda gittiğinden emin olur. Ve istisnai bir durumu düzeltmek için herhangi bir işlem yapamayacak.

kod Not
public void createAnyWorld(int population)
{
   try
   {
      createWorld(population);
   }
   catch (LonelyWorldException e)
   {
      e.printStackTrace();
   }
   catch (EmptyWorldException e)
   {
      e.printStackTrace();
   }
}
Tüm istisnalar bu yöntemde yakalanır. Arayan kişi, her şeyin yolunda gittiğinden emin olacaktır.


3. Birden fazla istisna yakalama

Programcılar kodu kopyalamaktan gerçekten nefret ederler. Hatta karşılık gelen bir geliştirme ilkesi buldular — DRY : Kendini Tekrarlama. Ancak istisnaları ele alırken, bir bloğun ardından aynı koda sahip birkaç bloğun geldiği sık durumlar vardır .trycatch

catchVeya aynı koda sahip 3 blok ve catchaynı koda sahip 2 blok daha olabilir . Bu, projeniz istisnaları sorumlu bir şekilde ele aldığında standart bir durumdur.

Sürüm 7'den başlayarak, Java dilinde tek bir blokta birden çok türde istisna belirtme yeteneği eklendi catch. Kabaca şöyle görünüyor:

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
   // Exception handling code
}

catchDilediğiniz kadar bloğa sahip olabilirsiniz . Ancak, tek bir catchblok birbirini miras alan istisnaları belirleyemez. Başka bir deyişle, sınıf miras aldığı için catch ( Exception| RuntimeExceptione) yazamazsınız .RuntimeExceptionException