1. İstisna türleri
Tüm istisnalar, aslında birbirini miras alan sınıflar olan 4 türe ayrılır.
Throwable
sınıf
Tüm istisnalar için temel sınıf, sınıftır Throwable
. Sınıf, Throwable
geç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.
Error
sı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. Error
Yapabileceğ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.
Exception
sınıf
Exception
ve 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
.
RuntimeException
sınıf
RuntimeExceptions
nin bir alt kümesidir Exceptions
. RuntimeException
Bunun 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.
Exception
ile 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 .
RuntimeException
veya öğesini devralan tüm istisnalar, denetlenmeyen istisnalarError
olarak kabul edilir . Diğer tüm istisnalar kontrol edilir .
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 ). Şuna benzer:throws
throw
type method (parameters) throws exception
Örnek:
işaretli istisna | denetlenmeyen istisna |
---|---|
|
|
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 throws
anahtar 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ü throws
anahtar 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.
catch
Ya her biri için bloklar ekleyerek ya da bunları yönteminiz için bir throws
yan 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 |
---|---|
|
Yöntem potansiyel olarak iki kontrol edilen istisna atar:
|
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 |
---|---|
|
Çağıran yöntem istisnaları yakalamaz ve diğerlerini onlar hakkında bilgilendirmek zorundadır: onları kendi throws yan 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 |
---|---|
|
Arayan yalnızca bir işaretli istisna yakalar — LonelyWorldException . throws Diğ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 |
---|---|
|
Tüm istisnalar bu yöntemde yakalanır. Arayan kişi, her şeyin yolunda gittiğinden emin olacaktır. |
3. Sarma istisnaları
Kontrol edilen istisnalar teoride harika görünüyordu, ancak pratikte büyük bir hayal kırıklığı olduğu ortaya çıktı.
Diyelim ki projenizde çok popüler bir yönteminiz var. Programınızdaki yüzlerce yerden çağrılır. Ve buna yeni bir işaretli istisna eklemeye karar veriyorsunuz . Ve bu kontrol edilen istisna gerçekten önemli ve o kadar özel olabilir ki, main()
yakalanırsa ne yapacağını yalnızca yöntem bilir.
Bu, süper popüler yönteminizi çağıran her yöntemin yan tümcesine işaretli istisnayı eklemeniz gerekeceğithrows
anlamına gelir . throws
Bu yöntemleri çağıran tüm yöntemlerin yan tümcesinde olduğu gibi . Ve bu yöntemleri çağıran yöntemlerden.
Sonuç olarak, throws
projedeki yöntemlerin yarısının yan tümceleri yeni bir kontrol edilen istisna alır. Ve tabii ki projeniz testlerle kapsanıyor ve artık testler derlenmiyor. Ve şimdi, testlerinizde throws yan tümcelerini de düzenlemeniz gerekiyor.
Ve sonra tüm kodunuz (yüzlerce dosyadaki tüm değişiklikler) diğer programcılar tarafından gözden geçirilmelidir. Ve bu noktada kendimize neden projede bu kadar çok kanlı değişiklik yaptığımızı soruyoruz. Çalışma günleri ve başarısız testler - hepsi kontrol edilen bir istisna eklemek uğruna mı ?
Ve elbette, kalıtım ve yöntem geçersiz kılma ile ilgili sorunlar hala var. Kontrol edilen istisnalardan kaynaklanan sorunlar, faydadan çok daha büyüktür. Sonuç olarak, artık çok az insan onları seviyor ve çok az insan kullanıyor.
Ancak yine de bu kontrol edilen istisnaları içeren çok sayıda kod (standart Java kitaplık kodu dahil) vardır . Onlarla ne yapılmalı? Onları görmezden gelemeyiz ve onlarla nasıl başa çıkacağımızı bilmiyoruz.
Java programcıları, kontrol edilen istisnaları RuntimeException
. Başka bir deyişle, kontrol edilen tüm istisnaları yakalayın ve ardından kontrol edilmeyen istisnalar oluşturun (örneğin, RuntimeException
) ve bunların yerine onları atın. Bunu yapmak şuna benzer:
try
{
// Code where a checked exception might occur
}
catch(Exception exp)
{
throw new RuntimeException(exp);
}
Bu çok güzel bir çözüm değil, ama burada suçlu bir şey yok: istisna basitçe bir RuntimeException
.
İstenirse, oradan kolayca alabilirsiniz. Örnek:
kod | Not |
---|---|
|
Nesnenin içinde saklanan istisnayı alın RuntimeException . Değişken cause , null türünü belirleyebilir ve kontrol edilen bir istisna türüne dönüştürebilir. |
4. Birden fazla istisna yakalama
Programcılar kodu kopyalamaktan gerçekten nefret ederler. Hatta buna karşılık gelen bir geliştirme ilkesi buldular: Kendini Tekrar Etme (DRY) . Ancak istisnaları ele alırken, bir bloğun ardından aynı koda sahip birkaç bloğun geldiği sık durumlar vardır .try
catch
catch
Veya aynı koda sahip 3 blok ve diğer aynı koda sahip 2 blok daha olabilir catch
. 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
. Şuna benzer:
try
{
// Code where an exception might occur
}
catch (ExceptionType1 | ExceptionType2 | ExceptionType3 name)
{
// Exception handling code
}
catch
Dilediğiniz kadar bloğa sahip olabilirsiniz . Ancak, tek bir catch
blok birbirini miras alan istisnaları belirleyemez. Başka bir deyişle, sınıf miras aldığı için catch ( Exception
| RuntimeException
e) yazamazsınız .RuntimeException
Exception
5. Özel istisnalar
Her zaman kendi istisna sınıfınızı oluşturabilirsiniz. Siz sadece sınıfı miras alan bir sınıf yaratırsınız RuntimeException
. Bunun gibi bir şey görünecek:
class ClassName extends RuntimeException
{
}
Siz OOP, kalıtım, yapıcılar ve metot geçersiz kılmayı öğrenirken detayları tartışacağız.
Ancak, yalnızca bunun gibi basit bir sınıfınız olsa bile (tamamen kodsuz), yine de buna dayalı olarak istisnalar oluşturabilirsiniz:
kod | Not |
---|---|
|
İşaretlenmemiş bir MyException . |
Java Multithreading arayışında , kendi özel istisnalarımızla çalışmayı derinlemesine inceleyeceğiz.
GO TO FULL VERSION