Bölüm 6: Hata Ayıklama ve İstisnalar
Giriş
Öğrenme Çıktıları
İstisnayı (exception) tanımlamak; derleme, çalışma zamanı ve mantık hatalarını ayırt etmek.
try, catch, finally ve try-with-resources ile istisnaları ele almak; akışı adım adım izlemek.
Throwable, Error, Exception, RuntimeException ilişkisini ve catch sırasının önemini açıklamak.
Kontrol edilen (checked) ve kontrol edilmeyen (unchecked) istisnaları ayırmak; “ele al veya bildir” kuralını uygulamak.
throw ile istisna fırlatmak, throws ile bildirmek; istisnanın çağrı yığınında yayılımını izlemek.
Yaygın istisna sınıflarını tanımak, özel istisna sınıfı yazmak ve izleme listesini (stack trace) okumak.
İstisna Kavramı
İstisna Nedir?
- İstisna (exception): program çalışırken ortaya çıkan, programın normal akışını bozan beklenmeyen bir durumdur.
- Örnek: açılmak istenen dosyanın bulunamaması, sıfıra bölme, dizinin dışına erişim,
nullbir referansın kullanılması. - İstisnalar Java çalışma zamanı sistemi (JVM) tarafından otomatik olarak ya da programcı tarafından kodla (
throw) oluşturulabilir. - Java'da istisna bir nesnedir: türünü, mesajını ve nerede oluştuğunu taşır.
- İstisna mekanizması, programcıya anormal durumlarla düzenli bir şekilde başa çıkma şansı verir.
Garson mutfakta yemeğin bittiğini öğrenir. Kendisi çözemez; durumu yöneticiye bildirir. Yönetici ya çözer (başka yemek önerir) ya da durumu bir üste iletir.
İstisna Kavramı
Üç Tür Hata
| Tür | Ne zaman? | Kim yakalar? | Örnek |
|---|---|---|---|
| Derleme hatası (compile-time error) | Program derlenirken | javac; program hiç çalışmaz | Noktalı virgül unutmak, int x = "a"; |
| Çalışma zamanı hatası (runtime error) → istisna | Program çalışırken | JVM bir istisna nesnesi fırlatır | 10 / 0, dizi[5] (3 elemanlı dizide) |
| Mantık hatası (logic error) | Program çalışır ama sonuç yanlış | Hiçbiri; testlerle bulunur | Ortalamada / 2 yerine / 3 yazmak |
Bu bölümün konusu ortadaki satırdır: istisnalar. Hata ayıklama (debugging) ise üç türün de nedenini bulup düzeltme işidir; istisna mekanizması ve izleme listesi bunun en güçlü araçlarındandır.
İstisna Kavramı
Yakalanmayan İstisna: Program Çöker
public class Cokus { public static void main(String[] args) { int pay = 10, payda = 0; System.out.println("Başla"); int sonuc = pay / payda; System.out.println("Sonuç: " + sonuc); System.out.println("Bitti"); } }
Başla
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Cokus.main(Cokus.java:5)- 5. satırda tamsayı sıfıra bölünür; JVM bir
ArithmeticExceptionnesnesi fırlatır. - Kimse yakalamadığı için program sonlanır: “Sonuç” ve “Bitti” hiç yazılmaz.
- JVM, istisnanın türünü, mesajını ve yerini (sınıf, metot, satır) yazdırır.
İstisna Kavramı
İstisnayla Başa Çıkmanın İki Yolu
Metot, istisna oluşturabilecek kodu try içine alır ve catch ile durumu kendisi çözer.
Örnek: dosya okuma metodu, dosya bulunamazsa (FileNotFoundException) kullanıcıya mesaj gösterip varsayılan ayarlarla devam eder.
Metot istisnayı ele almaz; imzasında throws ile bildirir. İstisna, metodu çağıran kodun sorunu olur.
Çağıran kod da aynı seçimle karşılaşır: ya ele alır ya da bir üste iletir.
İstisna Kavramı
“Ters Giden Bir Şey”: Dönüş Kodu ile
public static int indexOf(String[] isimler, String isim) { for (int i = 0; i < isimler.length; i++) { if (isimler[i].equals(isim)) { return i; } } return -1; } // main içinde String[] isimler = {"Ali", "Ayşe", "Can"}; System.out.println(indexOf(isimler, "Can")); int k = indexOf(isimler, "Ece"); // k = -1 System.out.println(isimler[k]);
2 java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 3
- İstisnalar, bir programın “bir şeyin ters gittiğini” bildirmesi için kullanılır.
- Ama “ters gitmek” özneldir: aranan ismin bulunamaması hata mıdır, olağan bir sonuç mu?
- Bu metot, eşleşme bulamazsa istisna fırlatmak yerine
-1döndürür. - Çağıran,
-1'i kontrol etmeyi unutursa hata başka bir yerde,isimler[-1]erişiminde ortaya çıkar (soldaki çıktı).
İstisna Kavramı
Öneri: İstisnaları Kullanın
public static int bul(String[] isimler, String isim) { for (int i = 0; i < isimler.length; i++) { if (isimler[i].equals(isim)) { return i; } } throw new IllegalArgumentException("Bulunamadı: " + isim); } // main içinde try { System.out.println(bul(isimler, "Ece")); } catch (IllegalArgumentException e) { System.out.println("Hata: " + e.getMessage()); }
Hata: Bulunamadı: Ece
- Genellikle
-1gibi özel dönüş kodlarından kaçınılmalı, Java'nın istisna mekanizması tercih edilmelidir. - İstisna, hata durumunu açık ve etkili biçimde ele almanın yoludur.
İstisnaların yararı
- Açık ve tutarlı hata işleme; hata normal sonuçla karışmaz
- Okunabilirlik artar, hata ayıklama kolaylaşır
- Kodun güvenilirliği artar
try ve catch
try ve catch İfadeleri
try { // Potansiyel hata içeren kodlar int sonuc = 10 / 0; // Hata: ArithmeticException } catch (ArithmeticException e) { // Hata durumuyla başa çıkma System.out.println("hata oluştu: " + e.getMessage()); }
hata oluştu: / by zero
- Hata yönetiminin temel yapısıdır.
trybloğu: potansiyel hata içeren kodlar.catchbloğu:tryiçinde belirtilen türde bir istisna oluşursa çalışır ve onu ele alır.catch (ArithmeticException e):e, fırlatılan istisna nesnesine referanstır (bir parametre gibi).- İstisna oluşursa
try'ın kalan satırları atlanır; istisna oluşmazsacatchhiç çalışmaz. - catch'ten sonra program normal akışına devam eder.
try ve catch · Kodu adım adım çalıştır
try-catch Akışı: Adım Adım
Değişkenler oluşur. payda sıfır: sorun yaklaşıyor.
try dışındaki normal kod çalışır.
try bloğuna girildi; ilk satır sorunsuz çalışır.
10 / 0: JVM bir ArithmeticException nesnesi oluşturur ve fırlatır. Atama yapılmaz.
Tür eşleşir: catch çalışır, e istisna nesnesini gösterir. “Sonuç” satırı atlandı.
e.getMessage() → "/ by zero".
Program çökmedi: catch'ten sonra normal akış devam eder.
public class BolmeOrnegi { public static void main(String[] args) { int pay = 10, payda = 0; System.out.println("Başla"); try { System.out.println("Bölme öncesi"); int sonuc = pay / payda; System.out.println("Sonuç: " + sonuc); } catch (ArithmeticException e) { System.out.println("Hata: " + e.getMessage()); } System.out.println("Bitti"); } }
try ve catch
İstisna Nesnesinden Bilgi Almak
try { int[] dizi = new int[3]; dizi[5] = 7; } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); System.out.println(e); System.out.println(e.getClass().getSimpleName()); e.printStackTrace(); }
Index 5 out of bounds for length 3
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3
ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3
at IstisnaNesnesi.main(IstisnaNesnesi.java:5)| Metot | Ne verir? |
|---|---|
getMessage() | Yalnızca açıklama mesajı (yoksa null) |
toString() | Tam sınıf adı + “: ” + mesaj; println(e) bunu kullanır |
getClass() | İstisnanın gerçek sınıfı |
printStackTrace() | toString() + izleme listesi; System.err'e yazar |
getCause() | Bu istisnaya yol açan başka istisna (varsa) |
try ve catch
Çoklu catch Bloğu
try { // Potansiyel hata içeren kodlar } catch (ArithmeticException e) { // ArithmeticException ile başa çıkma } catch (NullPointerException e) { // NullPointerException ile başa çıkma } catch (Exception e) { // Diğer hata türleri için genel durum }
- Bir kod bloğunda birden çok türde istisna oluşabilir.
- Her hata türü için ayrı bir
catchbloğu eklenir; her blok o türe özgü tepkiyi içerir. - İstisna fırlatıldığında catch blokları yukarıdan aşağıya sırayla denenir; eşleşen ilk blok çalışır, diğerleri atlanır.
- “Eşleşmek”: fırlatılan nesne, catch'teki türün kendisi veya alt sınıfıdır (
instanceofmantığı). - Son sıradaki
catch (Exception e)geri kalan tüm istisnaları yakalayan genel durumdur.
try ve catch
Zincirleme catch Blokları: Sıra Önemlidir
✗ Genel tür önce
try { int sonuc = 10 / 0; } catch (Exception e) { System.out.println("Genel hata"); } catch (ArithmeticException e) { System.out.println("Aritmetik hata"); }
SiraHatasi.java:7: error: exception ArithmeticException
has already been caught- catch türleri arasında kalıtım ilişkisi varsa sıralama önemlidir: alt sınıflar, üst sınıflardan önce gelmelidir.
ArithmeticExceptionbirException'dır; ilk blok onu zaten yakalar, ikinci blok asla çalışamaz. Derleyici buna izin vermez.- Kalıtım ilişkisi olmayan türlerin (
ArithmeticException,NullPointerException) sırası önemli değildir.
✓ Özelden genele
} catch (ArithmeticException e) { System.out.println("Aritmetik hata"); } catch (Exception e) { System.out.println("Genel hata"); }
try ve catch · Kodu adım adım çalıştır
Hangi catch Çalışır?
1. çağrı: parseInt("abc") → NumberFormatException. Bölme satırı atlanır.
İlk catch eşleşir ve çalışır; diğer catch'lere bakılmaz.
Ardından finally.
2. çağrı: 10 / 0 → ArithmeticException.
1. catch eşleşmez (✗), 2. catch eşleşir (✓).
3. çağrı: dizinin tek elemanı var; girdi[1] → ArrayIndexOutOfBoundsException.
İlk iki catch eşleşmez, üçüncüsü eşleşir; sonra finally.
static void bol(String[] girdi) { try { int x = Integer.parseInt(girdi[0]); int y = Integer.parseInt(girdi[1]); System.out.println("Sonuç: " + (x / y)); } catch (NumberFormatException e) { System.out.println("Sayı değil: " + e.getMessage()); } catch (ArithmeticException e) { System.out.println("Sıfır: " + e.getMessage()); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Eksik: " + e.getMessage()); } finally { System.out.println("finally çalıştı"); } } // main içinde bol(new String[] {"10", "abc"}); bol(new String[] {"10", "0"}); bol(new String[] {"10"});
try ve catch
Tek catch, Birden Çok Tür (Java 7+)
try { Object o = "Merhaba"; Integer i = (Integer) o; } catch (ClassCastException | NullPointerException e) { System.out.println("Tür veya null hatası: " + e.getClass().getSimpleName()); }
Tür veya null hatası: ClassCastException
- Tepki aynıysa türler
|ile birleştirilir; kod tekrarı azalır. - Bu blokta
efinal sayılır; yeni değer atanamaz.
✗ Alt ve üst sınıf birlikte yazılamaz
} catch (FileNotFoundException
| IOException e) {error: Alternatives in a multi-catch statement cannot be related by subclassing Alternative FileNotFoundException is a subclass of alternative IOException
catch (IOException e). Alt tür zaten onun içindedir.finally
finally Bloğu
try { // Potansiyel hata içeren kodlar } catch (Exception e) { // Diğer hata türleri için genel durum } finally { // Her durumda çalıştırılacak kodlar }
tryvecatchbloklarının ardından eklenir.- İstisna olsun veya olmasın, yakalansın veya yakalanmasın, her durumda çalışır.
tryveyacatchiçindereturnolsa bile, metottan çıkmadan önce çalışır.- Kodun belirli adımlarının çalışmasını güvence altına alır: dosya, ağ ve veritabanı bağlantılarını kapatmak gibi kaynak yönetimi ve temizlik işleri.
try'dan sonra en az bircatchveyafinallygelmelidir;try { } finally { }geçerlidir.- Tek istisna:
System.exit()JVM'i hemen durdurur; finally çalışmaz.
finally · Kodu adım adım çalıştır
finally ve return: Adım Adım
println'dan önce argümanı hesaplanmalı: bol(10, 2) çağrılır.
try bloğu başlar.
Bölme başarılı: s = 5.
return s: dönüş değeri 5 hazırlanır, ama metot hemen bitmez…
…önce finally çalışır. catch atlandı (istisna yok).
Şimdi 5 döner ve yazdırılır.
İkinci çağrı: bol(10, 0).
try başlar.
10 / 0 → istisna! try'ın kalanı (“try bitti”, return s) atlanır.
catch eşleşir ve mesajı yazar.
return -1: değer hazır, ama yine önce finally.
finally bu kez de çalışır.
-1 döner. Sonuç: finally iki durumda da çalıştı.
static int bol(int a, int b) { try { System.out.println("try başladı"); int s = a / b; System.out.println("try bitti"); return s; } catch (ArithmeticException e) { System.out.println("catch: " + e.getMessage()); return -1; } finally { System.out.println("finally"); } } public static void main(String[] args) { System.out.println("Sonuç = " + bol(10, 2)); System.out.println("Sonuç = " + bol(10, 0)); }
finally
try-with-resources (Java 7+)
class Kaynak implements AutoCloseable { private String ad; Kaynak(String ad) { this.ad = ad; System.out.println(ad + " açıldı"); } void kullan(int x) { System.out.println(ad + " kullanılıyor"); int s = 10 / x; } @Override public void close() { System.out.println(ad + " kapatıldı"); } }
try (Kaynak k = new Kaynak("dosya")) { k.kullan(0); } catch (ArithmeticException e) { System.out.println("Hata: " + e.getMessage()); }
dosya açıldı dosya kullanılıyor dosya kapatıldı Hata: / by zero
try (...)içinde açılan kaynak, blok bitince otomatik kapatılır (close()); istisna olsa bile.- Kaynak catch'ten önce kapanır. Kaynak sınıfı
AutoCloseablearayüzünü uygulamalıdır (dosya ve veritabanı sınıfları uygular). - Kaynak kapatmak için
finallyyazmanın modern ve güvenli yolu budur.
finally
İç İçe try Blokları
try { // Dıştaki try bloğu try { // İçteki try bloğu // Potansiyel hata içeren kodlar } catch (Exception e) { // İçteki catch bloğu } finally { // İçteki finally bloğu } } catch (Exception e) { // Dıştaki catch bloğu } finally { // Dıştaki finally bloğu }
Bir try bloğu içinde başka bir try bloğu bulunabilir. İçteki try'da bir istisna oluşursa:
- İçteki try'ın catch'lerinde uygun bir catch varsa o çalışır.
- Yoksa istisna dışa doğru ilerler; ilk uygun catch bulunur ve çalışır.
- Hiçbir catch eşleşmezse istisna metottan çıkar; sonunda kimse yakalamazsa JVM'in varsayılan işleyicisi programı sonlandırır.
- Her durumda, istisnanın geçtiği her seviyedeki
finally(varsa) çalışır.
finally · Kodu adım adım çalıştır
İç İçe try: İstisna Dışa Doğru İlerler
Dış try başlar.
İç try başlar; s = null.
null üzerinde metot çağrısı → NullPointerException.
İç catch yalnızca ArithmeticException yakalar: eşleşmez.
İstisna dışarı çıkmadan önce iç finally çalışır.
İstisna dış seviyeye geçti; “Dış try devam” atlandı. Dış catch eşleşir.
Dış finally çalışır.
İstisna ele alındı; program normal devam eder.
public static void main(String[] args) { try { System.out.println("Dış try"); try { System.out.println("İç try"); String s = null; System.out.println(s.length()); } catch (ArithmeticException e) { System.out.println("İç catch"); } finally { System.out.println("İç finally"); } System.out.println("Dış try devam"); } catch (NullPointerException e) { System.out.println("Dış catch: NPE"); } finally { System.out.println("Dış finally"); } System.out.println("Program sürüyor"); }
İstisna Hiyerarşisi
İstisnalar Hiyerarşisi
- Java'da istisna sınıfları bir sınıf hiyerarşisi içindedir.
Throwablesınıfı, fırlatılabilen her şeyin atasıdır: yalnızcaThrowableve alt sınıflarının nesnelerithrowedilebilir vecatchile yakalanabilir.Throwable'ın iki doğrudan alt sınıfı vardır:ErrorveException.- Bir
catchbloğu, yazılan türü ve tüm alt sınıflarını yakalar (kalıtımın doğal sonucu). - Java, yeni özel istisna sınıfları oluşturmayı destekler: uygulamaya özgü durumlara uyan sınıflar bu hiyerarşiye eklenir.
Aynı aileden istisnalar tek bir üst türle yakalanabilir: catch (IOException e) hem FileNotFoundException'ı hem de diğer giriş/çıkış hatalarını yakalar.
İstisna Hiyerarşisi
İstisna Sınıf Ağacı
İstisna Hiyerarşisi
Error ve Exception
Error
- Programın kurtarılamayacak ciddi bir sorunla karşılaştığını belirtir.
- Bu durumlarla başa çıkmak çoğunlukla mümkün değildir; genellikle programın sonlanmasına yol açar.
- Örnek: program belleğinin tükenmesi (
OutOfMemoryError), çağrı yığınının taşması, disk sürücüsünün “kaybolması” gibi aşırı durumlar. - Uygulama kodunda yakalanması önerilmez.
Exception
- Programın öngörebileceği ve çoğu zaman kurtarabileceği durumlar.
- Dosya yok, ağ koptu, geçersiz girdi,
nullreferans… try-catchile ele alınması beklenen türdür.- Alt sınıfı
RuntimeException, çoğunlukla programcı hatalarını temsil eder.
Her ikisi de Throwable'dan türer; bu yüzden ikisi de fırlatılabilir. Ama “ele alınmalı” olan, Exception ailesidir.
İstisna Türleri
İstisna Türleri
Derleme zamanında derleyici denetler; programcı ele almak ya da bildirmek zorundadır. Ortaya çıkabileceği önceden bilinen durumlar.
Derleme zamanında denetlenmez; çalışma zamanında ortaya çıkar. RuntimeException, Error ve alt sınıfları.
İstisna Türleri
Kontrol Edilen İstisna (Checked)
- Kod tarafından ele alınması veya bildirilmesi gerekir: “catch or declare” (yakala ya da bildir) kuralı.
- Metodun başında
throwsile belirtilmeli veyatry-catchiçinde ele alınmalıdır. Exception'dan türer amaRuntimeException'dan türemez.- Bu kural derleme zamanında denetlenir: uyulmazsa program derlenmez.
- Örnek: var olmayan bir dosyayı okumaya çalışmak. Program ne kadar doğru yazılsa da dosya silinmiş olabilir; bu yüzden derleyici bir plan ister.
✗ Ne ele alınmış ne bildirilmiş
public void dosyaOku() { FileReader okuyucu = new FileReader("veri.txt"); }
error: unreported exception FileNotFoundException; must be caught or declared to be thrown
✓ throws ile bildirilmiş
public void dosyaOku() throws FileNotFoundException { // Dosya okuma kodu FileReader okuyucu = new FileReader("veri.txt"); }
İstisna Türleri
Kontrol Edilen İstisnayı Ele Almak
public static void dosyaOku2() { try { FileReader okuyucu = new FileReader("veri.txt"); // Dosya okuma kodu } catch (FileNotFoundException e) { // Kontrol edilen istisna burada ele alınıyor System.err.println("Dosya bulunamadı: " + e.getMessage()); // Gerekirse istisna tekrar fırlatılabilir: // throw e; } }
Dosya bulunamadı: veri.txt (The system cannot find the file specified)
- Bu sürümde metot istisnayı kendisi yakalar; imzasında
throwsyoktur. Çağıran kod hiçbir şey yapmak zorunda değildir. System.err: hata çıktısı akışı. Konsolda çoğu IDE bunu kırmızı gösterir.- Mesaj, işletim sisteminden gelir; Windows ve Linux'ta farklıdır.
throw e;: yakalanan istisna, gerekirse (örneğin kayıt tuttuktan sonra) tekrar fırlatılabilir. O zaman metot yinethrows FileNotFoundExceptionbildirmelidir.
İstisna Türleri
Kontrol Edilmeyen İstisna (Unchecked)
- Ele alınması veya bildirilmesi zorunlu olmayan istisna türleridir.
- Genellikle mantık hataları veya programcı hataları sonucu ortaya çıkar: sıfıra bölme,
nullkullanımı, dizi sınırını aşma. throwsile belirtilmesi veyatry-catchiçine alınması zorunlu değildir; derleyici sessiz kalır.RuntimeExceptionveyaErrorsınıflarından türer.- Doğru çözüm çoğu zaman yakalamak değil, önlemektir: bölmeden önce paydayı, kullanmadan önce
null'ı denetlemek.
public void bolmeIslemi(int pay, int payda) { // Kontrol edilmeyen istisna: ArithmeticException int sonuc = pay / payda; }
Derlenir, throws gerekmez. payda == 0 olursa çalışma zamanında istisna oluşur.
public void bolmeIslemi(int pay, int payda) { if (payda == 0) { // önleme System.out.println("Payda sıfır olamaz"); return; } int sonuc = pay / payda; }
İstisna Türleri
Kontrol Edilen, Kontrol Edilmeyen, Error
| Kontrol edilen | Kontrol edilmeyen | Error | |
|---|---|---|---|
| Üst sınıf | Exception (RuntimeException hariç) | RuntimeException | Error |
| Derleyici denetler mi? | Evet: ele al veya bildir | Hayır | Hayır |
| Tipik neden | Programın dışındaki koşullar (dosya, ağ, veritabanı) | Programcı hatası (null, sınır, bölme) | JVM / sistem sorunu |
| Ne yapılmalı? | Yakala ve kurtar, ya da throws ile ilet | Kodu düzelt, girdiyi denetle | Genellikle yakalama; programı düzgün sonlandır |
| Örnekler | IOException, SQLException, ClassNotFoundException | NullPointerException, ArithmeticException | OutOfMemoryError, StackOverflowError |
İstisna Fırlatma
İstisna Fırlatma (Throwing an Exception)
- Java çalışma zamanı beklenmeyen bir durumla karşılaştığında, üst seviyedeki kodlara bildirmek için bir istisna nesnesi oluşturur ve fırlatır.
- Programcı da aynısını
throwanahtar kelimesiyle yapabilir. - İstisna, normal program akışını değiştirir:
throw'dan sonraki satırlar çalışmaz; denetim uyguncatch'e geçer. - Fırlatılabilen birçok tür vardır:
IOException,NullPointerException,IllegalArgumentException, kendi özel sınıflarınız… - Fırlatılan istisna, çağıran kod tarafından
try-catchile yakalanabilir. Hiçbir yerde ele alınmazsa JVM programı sonlandırır ve neyin yanlış gittiğini, nerede olduğunu bildirir.
Söz dizimi
throw new Exception("Bu bir istisna durumu!");
new ile istisna nesnesi oluşturulur (yapıcıya mesaj verilir), throw ile fırlatılır.
try { throw new Exception("Bu bir istisna durumu!"); } catch (Exception e) { System.out.println(e); }
java.lang.Exception: Bu bir istisna durumu!
İstisna Fırlatma
Durumu En İyi Anlatan Türü Fırlatın
class CustomException extends Exception { public CustomException(String mesaj) { super(mesaj); } } public static void kontrolEt(int deger) throws CustomException { if (deger < 0) { // Belirli bir durumu kontrol et ve istisna fırlat throw new CustomException("Değer negatif olamaz!"); } // Değer pozitifse, normal işlem devam eder System.out.println("Değer uygun: " + deger); } // main içinde try { kontrolEt(5); kontrolEt(-3); kontrolEt(8); } catch (CustomException e) { System.out.println("Yakalandı: " + e.getMessage()); }
Değer uygun: 5 Yakalandı: Değer negatif olamaz!
- İstisna türü seçilirken durumu en iyi temsil eden sınıf seçilmelidir.
- Özel senaryolar için özel istisna sınıfları oluşturulabilir (ayrıntısı ileride).
CustomExceptionbirExceptionalt sınıfıdır: kontrol edilen bir istisnadır. Bu yüzden metot imzasındathrows CustomExceptionşarttır.kontrolEt(-3)fırlattığı anda try'ın kalanı atlanır:kontrolEt(8)hiç çağrılmaz.
İstisna Fırlatma
throw ve throws Farkı
throw | throws | |
|---|---|---|
| Görevi | Bir istisnayı fırlatır (şimdi) | Metodun fırlatabileceği istisnaları bildirir (ileride olabilir) |
| Yeri | Metot gövdesinde, bir deyim olarak | Metot imzasında, parametrelerden sonra |
| Ardından | Tek bir nesne: throw new X("…"); | Bir veya daha çok tür: throws X, Y |
| Örnek | throw new ArithmeticException("Sıfıra bölme"); | void bol(int x, int y) throws ArithmeticException |
✗ throws gövdede kullanılmaz
if (x < 0) { throws new IllegalArgumentException("negatif"); }
error: illegal start of expression
✗ Kontrol edilen istisna, bildirilmeden fırlatılmış
static void f(int x) { if (x < 0) throw new Exception("negatif"); }
error: unreported exception Exception; must be caught or declared to be thrown
İstisna Fırlatma
İstisna Fırlatan Metotları Çağırmak
Dosya okuma metodu
public void dosyaOku() throws FileNotFoundException { // Dosya okuma kodu }
1) Çağıran ele alır (tercih edilen)
try { dosyaOku(); } catch (FileNotFoundException e) { // Dosya bulunamadı durumuyla başa çıkma kodu System.err.println("Dosya bulunamadı: " + e.getMessage()); }
2) Çağıran da bildirir (iletir)
public void raporHazirla() throws FileNotFoundException { dosyaOku(); }
- Metot çağırırken, metodun imzasında belirtilen istisnalar dikkate alınmalı ve uygun bir strateji seçilmelidir.
- Çağrı, uygun
try-catchbloğunun içine yazılır. - Ya da çağıran metot da imzasında
throwsile aynı türü bildirir; sorun bir üst seviyeye geçer. Bu, sorunu yalnızca ertelediği için yakalamaktan daha az tercih edilir. mainbilethrowsyazabilir; o zaman yakalanmayan istisna programı sonlandırır.
İstisna Fırlatma · Kodu adım adım çalıştır
Yayılım: İstisna Çağrı Yığınında İner
main, try içinde hesapla(10)'u çağırır.
Yığına hesapla çerçevesi eklendi.
hesapla, bol(10, 0)'ı çağırır.
Yığının tepesinde artık bol var.
10 / 0: istisna bol'da doğdu. bol'da try yok → bol'un kalanı çalışmaz, çerçevesi atılır.
İstisna çağıran yere, hesapla'ya geçti. Burada da try yok → “hesapla bitti” atlanır, çerçeve atılır.
İstisna main'e ulaştı. Çağrı bir try içinde: uygun catch aranır. “Sonuç” satırı atlanır.
catch eşleşti: istisna yakalandı, yayılım durdu.
Program normal biçimde biter. Kimse yakalamasaydı JVM programı sonlandırırdı.
static int bol(int a, int b) { System.out.println("bol başladı"); int s = a / b; System.out.println("bol bitti"); return s; } static int hesapla(int x) { System.out.println("hesapla başladı"); int r = bol(x, 0); System.out.println("hesapla bitti"); return r; } public static void main(String[] args) { try { int sonuc = hesapla(10); System.out.println("Sonuç: " + sonuc); } catch (ArithmeticException e) { System.out.println("main: " + e.getMessage()); } System.out.println("Program bitti"); }
İstisna Fırlatma
JVM İstisnayı Nasıl Ele Alır?
- JVM (veya
throw) bir istisna nesnesi oluşturur: türü, mesajı ve oluştuğu yerin izleme listesi (stack trace) içindedir. - İstisnanın oluştuğu metotta, onu saran bir
tryve uyumlu bircatcharanır. - Bulunamazsa metot o anda sona erer (varsa
finallyçalışır) ve istisna çağıran metoda geçer. Arama, çağrı yığınında aşağıya doğru sürer. - Uygun bir catch bulunursa o çalışır; program catch'ten sonra devam eder.
mainde yakalamazsa JVM'in varsayılan işleyicisi izleme listesini yazdırır ve programı (o iş parçacığını) sonlandırır.
Çalışma Zamanı İstisnaları
RuntimeException Sınıfları
RuntimeException ve alt sınıfları, programcı hatası veya mantık hatası sonucu oluşan istisnaları temsil eder. Derleme zamanında denetlenmez, ele alınmaları zorunlu değildir; ama programcının bu durumları bilinçli olarak önlemesi ya da ele alması gerekir.
| Sınıf | Ne zaman oluşur? | Örnek |
|---|---|---|
NullPointerException | null bir referansın üyesi kullanılınca | String s = null; s.length(); |
ArrayIndexOutOfBoundsException | Dizi sınırları dışında indeks | int[] d = new int[3]; d[5] = 1; |
ArithmeticException | Tamsayı sıfıra bölme, kesin aritmetikte taşma | 10 / 0 |
IllegalArgumentException | Metoda geçersiz argüman verilince | new ArrayList<>(-1) |
NumberFormatException | Metin geçerli bir sayı değilken dönüştürme | Integer.parseInt("abc") |
ClassCastException | Nesne, dönüştürülmek istenen türde değilken | (Integer) nesne |
Çalışma Zamanı İstisnaları
NullPointerException
nullbir referans üzerinden metot çağırmak, alana erişmek veyalengthalmak bu istisnaya yol açar.- En sık hata kaynaklarındandır. Önlemek için:
if (str != null)ile açık denetimObjects.requireNonNull(x, mesaj):nullise hemen, anlamlı mesajla NPE fırlatırObjects.requireNonNullElse(x, varsayilan)(Java 9+):nullise varsayılan değeri döndürürOptionalsınıfı (Java 8+): “değer olmayabilir” durumunu açıkça temsil eder- Kütüphaneler: Apache Commons Lang
StringUtils,null-güvenli metin işlemleri sunar
String str = null; int length = str.length();
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
null olduğunu söyler. Değişken adı hata ayıklama bilgisiyle derlenince (javac -g, IDE'ler) görünür; yoksa "<local1>".Çalışma Zamanı İstisnaları
null ile Güvenli Çalışmak
1String str = null; 2int length = str.length(); 3Objects.requireNonNull(str, "Str null olamaz"); 4Optional<String> optionalStr = Optional.ofNullable(str); 5length = optionalStr.map(String::length).orElse(0); 6String defaultValue = Objects.requireNonNullElse(str, "0"); 7if (str != null) { 8 System.out.println(str.length()); 9} 10System.out.println("Ali".equals(str));
| Satır | Sonuç (her satır tek başına denendiğinde) |
|---|---|
| 2 | NullPointerException: Cannot invoke "String.length()" because "str" is null |
| 3 | NullPointerException: Str null olamaz |
| 5 | length = 0 (değer yok → orElse(0)) |
| 6 | defaultValue = "0" |
| 7–9 | Koşul yanlış; hiçbir şey yazılmaz, istisna yok |
| 10 | false: sabit metin önde, null argüman sorun değil |
"Ali".equals(str) güvenlidir; str.equals("Ali") ise str null olduğunda NPE fırlatır. requireNonNull, hatayı kaynağında ve anlaşılır bir mesajla yakalamak için metot başlarında kullanılır.
Çalışma Zamanı İstisnaları
ArrayIndexOutOfBoundsException
- Dizinin sınırları dışındaki bir indekse erişme durumudur: geçerli indeksler
0…length − 1; negatif indeks de geçersizdir. IndexOutOfBoundsExceptionailesinin bir üyesidir. Sınır aşımında aynı aileden farklı sınıflar fırlatılabilir:- dizi (
int[]),Vector,Arrays.asList(...)listesi →ArrayIndexOutOfBoundsException ArrayList.get→IndexOutOfBoundsException(üst sınıf)String.charAt→StringIndexOutOfBoundsException
- dizi (
- Hepsini birden yakalamak için:
catch (IndexOutOfBoundsException e).
Önleme: döngü sınırını length ile yazın
int[] numbers = {1, 2, 3}; for (int i = 0; i < numbers.length; i++) { System.out.print(numbers[i] + " "); }
1 2 3
i <= dizi.length yazmak. Son tur dizi[length]'e erişir ve istisna oluşur.Çalışma Zamanı İstisnaları
Sınır Aşımı: Hangi Satır Hangi İstisna?
1int[] numbers = {1, 2, 3}; 2int value = numbers[5]; 3ArrayList<String> list = new ArrayList<>(); 4String svalue = list.get(5); 5Vector<Integer> vector = new Vector<>(); 6value = vector.get(10); 7String[] names = {"Alice", "Bob", "Charlie"}; 8svalue = Arrays.asList(names).get(5); 9String str = "Hello"; 10char ch = str.charAt(10);
| Satır | Fırlatılan istisna ve mesajı |
|---|---|
| 2 | ArrayIndexOutOfBoundsExceptionIndex 5 out of bounds for length 3 |
| 4 | IndexOutOfBoundsExceptionIndex 5 out of bounds for length 0 |
| 6 | ArrayIndexOutOfBoundsExceptionArray index out of range: 10 |
| 8 | ArrayIndexOutOfBoundsExceptionIndex 5 out of bounds for length 3 |
| 10 | StringIndexOutOfBoundsExceptionIndex 10 out of bounds for length 5 |
Her satır tek başına denendiğinde. Boş bir ArrayList'in kapasitesi olsa bile boyutu 0'dır; get boyuta göre denetler.
Çalışma Zamanı İstisnaları
ArithmeticException
- Matematiksel işlemler sırasında oluşan bir hatayı temsil eder; en bilinen örneği tamsayıyı sıfıra bölmek (
/ve%). Mathsınıfının “kesin” (exact) metotları taşmada fırlatır:addExact,multiplyExact,toIntExact…BigDecimalyüksek hassasiyetli aritmetik sağlar; sıfıra bölmede veya sonucu tam gösterilemeyen bölmede (1/3) fırlatır.- Dikkat:
doubleişlemleri istisna fırlatmaz:10.0 / 0→Infinity,Math.sqrt(-1)→NaN. Random.nextInt(0)iseArithmeticExceptiondeğil,IllegalArgumentExceptionfırlatır: sınır pozitif olmalıdır.
int toplaması taşınca istisna oluşmaz, değer başa sarar:Integer.MAX_VALUE + 1 → -2147483648.Taşmanın fark edilmesi gerekiyorsa
Math.addExact kullanın.Çalışma Zamanı İstisnaları
Aritmetik Hatalar: Satır Satır
1int result = 10 / 0; 2double dresult = Math.sqrt(-1); 3System.out.println(dresult); 4System.out.println(10.0 / 0); 5int t = Math.addExact(Integer.MAX_VALUE, 1); 6Random random = new Random(); 7int randomNumber = random.nextInt(0); 8BigDecimal num1 = new BigDecimal("10"); 9BigDecimal num2 = BigDecimal.ZERO; 10BigDecimal bresult = num1.divide(num2);
| Satır | Sonuç |
|---|---|
| 1 | ArithmeticException: / by zero |
| 3 | NaN yazar, istisna yok |
| 4 | Infinity yazar, istisna yok |
| 5 | ArithmeticException: integer overflow |
| 7 | IllegalArgumentException: bound must be positive |
| 10 | ArithmeticException: Division by zero |
Her satır tek başına denendiğinde. Kayan noktalı sayılarda sıfıra bölme IEEE 754 kurallarına göre özel değerler (Infinity, NaN) üretir; bu yüzden double sonuçlarını ayrıca denetlemek gerekir (Double.isNaN).
Çalışma Zamanı İstisnaları
IllegalArgumentException
- Bir metodun geçersiz bir argüman aldığını belirtir. Kontrol edilmeyen bir istisnadır.
- Argümanları denetleyip fırlatmak, hatayı kaynağında durdurur.
- Kütüphane örnekleri:
Arrays.copyOfRange(d, 5, 2): başlangıç > bitişnew ArrayList<>(-1): negatif kapasiteThread'insetPriority(11): öncelik 1–10 arası olmalınew File(uri): adresfile:şeklinde değilse
public void yasAyarla(int age) { if (age < 0) { throw new IllegalArgumentException("Yaş negatif olamaz"); } this.age = age; } public void adAyarla(String name) { if (name.length() < 3) { throw new IllegalArgumentException("3 karakter olmalı"); } this.name = name; }
new FileReader("invalid/file/path") → FileNotFoundException; new Thread(null) hiç fırlatmaz. Alt sınıfı: NumberFormatException.Çalışma Zamanı İstisnaları
Geçersiz Argüman: Satır Satır
1yasAyarla(-5); 2adAyarla("Al"); 3int[] numbers = {1, 2, 3}; 4Arrays.copyOfRange(numbers, 5, 2); 5List<Integer> liste = new ArrayList<>(-1); 6File file = new File(URI.create("http://ornek.com/a.txt")); 7Thread thread = new Thread(gorev); 8thread.setPriority(11);
| Satır | Fırlatılan istisna (her satır tek başına) |
|---|---|
| 1 | IllegalArgumentException: Yaş negatif olamaz |
| 2 | IllegalArgumentException: 3 karakter olmalı |
| 4 | IllegalArgumentException: 5 > 2 |
| 5 | IllegalArgumentException: Illegal Capacity: -1 |
| 6 | IllegalArgumentException: URI scheme is not "file" |
| 8 | IllegalArgumentException (mesajsız) |
İyi bir mesaj, geçersiz değeri ve beklenen aralığı söyler: "Yaş negatif olamaz: " + age. Mesajsız istisna (8. satır) hata ayıklamayı zorlaştırır.
Çalışma Zamanı İstisnaları
NumberFormatException
- Bir metin sayıya dönüştürülürken metin geçerli bir sayıyı temsil etmiyorsa oluşur.
Integer.parseInt,Double.parseDouble,Float.parseFloat,Short.parseShort,Long.parseLong,Byte.parseBytevevalueOfmetotları fırlatabilir.- Değer türün aralığı dışındaysa da oluşur:
Byte.parseByte("300"). IllegalArgumentException'ın alt sınıfıdır.- Kullanıcı girdisi her zaman bu riski taşır: ya önceden denetleyin ya da yakalayın.
String strNumber = "abc"; int number = Integer.parseInt(strNumber); strNumber = "123abc"; number = Integer.parseInt(strNumber); String strDouble = "12.34abc"; double doubleValue = Double.parseDouble(strDouble); String strShort = "45xyz"; short shortValue = Short.parseShort(strShort);
| Çağrı | NumberFormatException mesajı |
|---|---|
Integer.parseInt("abc") | For input string: "abc" |
Integer.parseInt("123abc") | For input string: "123abc" |
Double.parseDouble("12.34abc") | For input string: "12.34abc" |
Short.parseShort("45xyz") | For input string: "45xyz" |
Çalışma Zamanı İstisnaları
Güvenli Sayı Dönüştürme
static int guvenliOku(String metin, int varsayilan) { try { return Integer.parseInt(metin.trim()); } catch (NumberFormatException e) { return varsayilan; } } // main içinde System.out.println(guvenliOku(" 42 ", 0)); System.out.println(guvenliOku("kırk", 0)); System.out.println(guvenliOku("10.5", -1));
42 0 -1
- Dönüştürme bir yardımcı metotta tek bir yerde denetlenir; geçersiz girdi için varsayılan değer döner.
trim(), baştaki ve sondaki boşlukları siler:parseInt(" 42 ")tek başına istisna fırlatırdı."10.5"birintdeğildir; ondalık sayı içinDouble.parseDoublekullanılır.- Varsayılan değer, geçerli bir sonuçla karışmayacak biçimde seçilmelidir; karışabiliyorsa istisnayı çağırana iletmek daha doğrudur.
Çalışma Zamanı İstisnaları
ClassCastException
- Bir nesne, dönüştürülmek istendiği türden değilken tür dönüşümü (cast) yapılınca oluşur.
- Değişkenin türü değil, nesnenin gerçek türü belirleyicidir:
Object obj = "Merhaba"birStringnesnesidir. - Ham (raw) türlü koleksiyonlar (
ArrayList,Map,Set) her türü kabul eder; yanlış türde eleman alınırken dönüşüm başarısız olur. Sıralı koleksiyonlar (TreeSet,TreeMap) karşılaştırılamayan türde eleman eklenirken de fırlatır. - Önleme: generics (
ArrayList<String>) yanlış türü derleme zamanında yakalar; dönüşümden önceinstanceofile denetleyin.
1Object obj = "Merhaba"; 2Integer number = (Integer) obj; 3ArrayList list = new ArrayList(); 4list.add("Merhaba"); 5number = (Integer) list.get(0); 6Map map = new HashMap(); 7map.put("anahtar", "Değer"); 8Integer value = (Integer) map.get("anahtar"); 9Set set = new HashSet(); 10set.add("Merhaba"); 11value = (Integer) set.iterator().next(); 12Object[] objArray = new String[5]; 13Integer[] intArray = (Integer[]) objArray;
2, 5, 8, 11 ve 13. satırların her biri ClassCastException fırlatır, örneğin:
class java.lang.String cannot be cast to class java.lang.Integer
Çalışma Zamanı İstisnaları
Dönüşümden Önce instanceof
Klasik biçim
Object obj = "Merhaba"; if (obj instanceof Integer) { Integer sayi = (Integer) obj; System.out.println("Sayı: " + sayi); } else { System.out.println("obj bir Integer değil"); }
obj bir Integer değil
Desen eşleme (Java 16+)
if (obj instanceof Integer sayi) { System.out.println("Sayı: " + sayi); }
Generics ile derleme zamanında
ArrayList<String> liste = new ArrayList<>();
liste.add("Merhaba");
Integer n = (Integer) liste.get(0);error: incompatible types: String cannot be converted to Integer
Kontrol Edilen Sınıflar
Kontrollü İstisna Sınıfları
Kodun hatayı ele alması ve uygun biçimde kurtarması gereken, çoğunlukla programın dışındaki koşullardan doğan durumları temsil eder. Derleyici ele alınmalarını şart koşar.
| Sınıf | Paket | Ne zaman? |
|---|---|---|
FileNotFoundException | java.io | Açılmak istenen dosya yok veya açılamıyor |
IOException | java.io | Giriş/çıkış işlemlerinde genel hata (üst sınıf) |
SQLException | java.sql | Veritabanı erişiminde hata |
ParseException | java.text | Metni bir biçime göre ayrıştırırken hata |
ClassNotFoundException | java.lang | Adıyla yüklenmek istenen sınıf bulunamadı |
InterruptedException | java.lang | Bekleyen iş parçacığı kesildi (Thread.sleep) |
NotSerializableException | java.io | Serileştirilemeyen nesne yazılmak istendi |
Kontrol Edilen Sınıflar
FileNotFoundException
try { FileReader fileReader = new FileReader("dosya.txt"); } catch (FileNotFoundException e) { // Dosya bulunamadı durumuyla ilgili işlemler System.out.println(e); }
java.io.FileNotFoundException: dosya.txt (The system cannot find the file specified)
- Bir dosya açılmak istendiğinde dosya bulunamazsa (ya da bir klasörse, okuma izni yoksa) oluşur.
IOException'ın alt sınıfıdır;catch (IOException e)onu da yakalar.- Göreli yol (
"dosya.txt"), programın çalışma klasörüne göre aranır. IDE'lerde bu genellikle proje klasörüdür: dosya “yanlış klasörde” olabilir. - Tipik tepki: kullanıcıya bildirip yeni bir ad istemek veya varsayılan değerlerle devam etmek.
Kontrol Edilen Sınıflar
IOException
try { BufferedReader reader = new BufferedReader(new FileReader(path)); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } reader.close(); } catch (IOException e) { // IOException durumuyla ilgili işlemler e.printStackTrace(); }
birinci satır ikinci satır
- Giriş/çıkış işlemlerinde oluşan genel hatayı temsil eder;
FileNotFoundExceptiongibi birçok alt sınıfı vardır. - Sorun:
readLine()istisna fırlatırsareader.close()hiç çalışmaz; dosya açık kalır (kaynak sızıntısı).
✓ try-with-resources ile
try (BufferedReader okuyucu = new BufferedReader(new FileReader(path))) { String satir; while ((satir = okuyucu.readLine()) != null) { System.out.println(satir); } } catch (IOException e) { System.out.println(e.getMessage()); }
Kontrol Edilen Sınıflar
SQLException
try { Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/okul"); PreparedStatement preparedStatement = connection.prepareStatement("SELECT user_id FROM users"); // Sorguyu çalıştırma ve sonuçları alıp işleme ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { // Sonuçları işleme System.out.println("User ID: " + resultSet.getInt("user_id")); } // Bağlantıyı kapatma connection.close(); } catch (SQLException e) { // SQLException durumuyla ilgili işlemler System.out.println(e); }
- Veritabanı işlemleri sırasında bir hata oluştuğunda fırlatılır: bağlantı kurulamadı, SQL sözdizimi yanlış, tablo yok, sürücü yok…
getMessage(),getSQLState()vegetErrorCode()ayrıntı verir.
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost/okul
Bağlantı da bir kaynaktır; try-with-resources ile kapatılmalıdır. Veritabanı konusu Bölüm 10'da ele alınır.
Kontrol Edilen Sınıflar
ParseException ve ClassNotFoundException
ParseException (java.text)
Bir metin belirli bir biçime göre ayrıştırılırken uyuşmazlık olursa fırlatılır.
try { SimpleDateFormat form = new SimpleDateFormat("dd/MM/yy"); Date date = form.parse("01-01-2022"); } catch (ParseException e) { // Ayrıştırma hatasıyla ilgili işlemler System.out.println(e); }
java.text.ParseException: Unparseable date: "01-01-2022"
Biçim / bekliyor, metinde - var.
ClassNotFoundException
Bir sınıf adıyla yüklenmek istenirken (Class.forName) sınıf bulunamazsa fırlatılır.
try { Class.forName("java.util.Scanner"); System.out.println("Scanner yüklendi"); // Var olmayan bir sınıfı yüklemeye çalışma Class.forName("com.example.NonExistentClass"); } catch (ClassNotFoundException e) { System.out.println(e); }
Scanner yüklendi java.lang.ClassNotFoundException: com.example.NonExistentClass
Kontrol Edilen Sınıflar
NotSerializableException
class Nokta { // Serializable değil int x = 3, y = 4; } // main içinde try (ObjectOutputStream outputStream = new ObjectOutputStream(new ByteArrayOutputStream())) { // Nesneyi ObjectOutputStream ile serileştirmeye çalışma Nokta notSerializableObj = new Nokta(); outputStream.writeObject(notSerializableObj); } catch (NotSerializableException e) { System.out.println(e); } catch (IOException e) { System.out.println("Diğer G/Ç hatası: " + e); }
java.io.NotSerializableException: Nokta
- Serileştirme (serialization): bir nesnenin bayt akışına dönüştürülmesi (dosyaya yazmak, ağdan göndermek) ve daha sonra geri dönüştürülmesidir.
Serializablearayüzünü uygulayan sınıf serileştirilebilir kabul edilir; uygulamayan sınıfın nesnesi yazılmak istenince bu istisna oluşur.IOException'ın (dolaylı) alt sınıfıdır; bu yüzden catch'iIOException'dan önce yazılır.
✓ Çözüm
class Nokta implements Serializable { int x = 3, y = 4; }
Error Sınıfları
Error Sınıfları
- Programın normal çalışmasını temelden etkileyen, sistem düzeyindeki sorunları temsil eden kontrol edilmeyen türlerdir.
- Genellikle uygulama kodunun bir satırından değil, JVM'in ve ortamın durumundan kaynaklanır.
- JVM tarafından fırlatılır; ele alınması veya bildirilmesi önerilmez. Programın düzgün biçimde sonlanması daha uygun bir yaklaşımdır.
- Yine de
Throwableoldukları için teknik olarakcatchedilebilirler (bir sonraki slayt).
| Hata | Ne zaman? |
|---|---|
OutOfMemoryError | Bellek (heap) tükendi |
StackOverflowError | Çağrı yığını taştı: genellikle sonsuz özyineleme |
AssertionError | assert koşulu yanlışsa (yalnızca -ea açıkken) |
NoClassDefFoundError | Derlemede var olan sınıf çalışırken bulunamadı |
Error Sınıfları
Error Örnekleri
static void sonsuz() { sonsuz(); // durma koşulu yok } public static void main(String[] args) { try { sonsuz(); } catch (StackOverflowError e) { System.out.println("SOE -> " + e); } try { long[] dizi = new long[Integer.MAX_VALUE]; } catch (OutOfMemoryError e) { System.out.println("OOM -> " + e); } int yas = -5; assert yas >= 0 : "Yaş negatif: " + yas; System.out.println("assert geçti"); }
SOE -> java.lang.StackOverflowError OOM -> java.lang.OutOfMemoryError: Requested array size exceeds VM limit assert geçti
SOE -> java.lang.StackOverflowError OOM -> java.lang.OutOfMemoryError: Requested array size exceeds VM limit Exception in thread "main" java.lang.AssertionError: Yaş negatif: -5
- Özyinelemede taban durum unutulursa her çağrı yeni bir çerçeve ekler; yığın dolar.
assertvarsayılan olarak kapalıdır;-eaile açılır. Geliştirirken varsayımları sınamak içindir. (Burada yakalamak yalnızca gösterim içindir.)
Özel İstisnalar
Özel İstisna Sınıfları
public class OzelHata extends Exception { // Constructor public OzelHata(String message) { super(message); } }
| Üst sınıf | Sonuç |
|---|---|
extends Exception | Kontrol edilen: çağıran ele almak zorunda; kurtarılabilir iş kuralı ihlalleri |
extends RuntimeException | Kontrol edilmeyen: hatalı kullanım, programcı hatası |
- Geliştirici, kendi programında ortaya çıkabilecek beklenmeyen durumları yönetmek için özel istisna sınıfları oluşturabilir.
Throwable'ı genişleten her sınıfın nesnesi fırlatılabilir. Ancak genellikleExceptionveyaRuntimeExceptiongenişletilir;ErrorveThrowabledoğrudan genişletilmez.- Yapıcı, mesajı
super(message)ile üst sınıfa iletir; böylecegetMessage()çalışır. - Ad
…Hata/…Exceptionile bitirilir; durumu anlatmalıdır. - Ek alanlar (eksik tutar, hatalı değer) eklenebilir: istisna sıradan bir sınıftır.
Özel İstisnalar
Özel İstisnayı Fırlatmak ve Yakalamak
public class OzelHataTest { public static void main(String[] args) { try { fonksiyon(); } catch (OzelHata e) { System.out.println("Yakalandı: " + e.getMessage()); } } public static void fonksiyon() throws OzelHata { if (true) { throw new OzelHata("Özel hata oluştu."); } } }
Yakalandı: Özel hata oluştu.
OzelHata,Exception'dan türediği için kontrol edilen bir istisnadır:fonksiyon()imzasındathrows OzelHatazorunludur.main, çağrıyıtryiçine alarak “ele al” seçeneğini kullanır.if (true)burada yalnızca gösterim içindir: koşulsuzthrow'dan sonra gelen bir kod “unreachable statement” hatası verirdi.- Gerçek programlarda koşul bir iş kuralını denetler: bakiye yeterli mi, not 0–100 arasında mı, kullanıcı adı boş mu…
Özel İstisnalar · Kodu adım adım çalıştır
Özel İstisna: Banka Hesabı
Hesap nesnesi heap'te oluşur; hesap onu gösterir.
paraCek(30): 30 > 100 mü? Hayır; istisna yok.
Bakiye 70.0 olur ve yazdırılır.
paraCek(90): 90 > 70 mi? Evet.
Heap'te bir istisna nesnesi oluşur (mesaj ve eksik = 20.0) ve fırlatılır. Bakiye değişmez.
paraCek'in çerçevesi atılır; paraCek(10) atlanır. catch eşleşir: e aynı nesneyi gösterir.
İstisna nesnesinin bilgileri kullanılır. İstisna da sıradan bir nesnedir.
class Hesap { private double bakiye; Hesap(double bakiye) { this.bakiye = bakiye; } public void paraCek(double miktar) throws YetersizBakiyeHatasi { if (miktar > bakiye) { throw new YetersizBakiyeHatasi( "Bakiye yetersiz", miktar - bakiye); } bakiye -= miktar; System.out.println("Kalan: " + bakiye); } } // main içinde Hesap hesap = new Hesap(100); try { hesap.paraCek(30); hesap.paraCek(90); hesap.paraCek(10); } catch (YetersizBakiyeHatasi e) { System.out.println(e.getMessage() + ", eksik: " + e.getEksik()); }
Özel İstisnalar
Bilgi Taşıyan Özel İstisna
class YetersizBakiyeHatasi extends Exception { private double eksik; public YetersizBakiyeHatasi(String mesaj, double eksik) { super(mesaj); // mesaj Throwable'da saklanır this.eksik = eksik; } public double getEksik() { return eksik; } }
- Önceki izlemede kullanılan sınıf: mesaja ek olarak eksik tutarı da taşır.
- Yakalayan kod bu bilgiyle anlamlı bir tepki verebilir: “20 TL eksik; yine de denemek ister misiniz?”
-1gibi bir dönüş kodu bu kadar bilgi taşıyamazdı.- Kontrol edilen tür seçildi: yetersiz bakiye öngörülebilir bir durumdur ve çağıran kod bununla başa çıkmalıdır.
İzleme Listesi
İzleme Listesi (Stack Trace)
- Program çalışırken hangi metot çağrılarının gerçekleştiğini ve istisnanın nerede oluştuğunu gösteren rapordur.
- İstisnanın türünü ve mesajını; her çağrı için sınıf ve metot adını, dosya adını ve satır numarasını içerir.
- Yakalanmayan bir istisnada JVM tarafından konsola (
System.err) yazdırılır;e.printStackTrace()ile istenildiğinde de yazdırılabilir. - Programcının hatayı anlamasına ve sorunu çözmesine yardım eden en önemli ipucudur.
Exception in thread "main" java.lang.NullPointerException
at com.example.MyClass.myMethod(MyClass.java:10)
at com.example.MyClass.main(MyClass.java:6)Okuma: main (6. satır) myMethod'u çağırdı; istisna myMethod'un 10. satırında oluştu. com.example paket, MyClass sınıf adıdır.
İzleme Listesi
İzleme Listesini Okumak
1public class IzlemeOrnegi { 2 static int uzunluk(String metin) { 3 return metin.length(); 4 } 5 static void yazdir(String ad) { 6 System.out.println(ad + ": " + uzunluk(ad)); 7 } 8 public static void main(String[] args) { 9 yazdir("Ali"); 10 yazdir(null); 11 System.out.println("Bitti"); 12 } 13}
- İlk satır: tür ve mesaj:
metinnull. - İlk
at: istisnanın doğduğu yer (3. satır). - Aşağı doğru çağrı zinciri:
main(10) →yazdir(6) →uzunluk(3). - Kendi kodunuzdaki satırlara bakın; asıl neden çoğu zaman aşağıdadır:
null'ı 10. satır gönderdi.
Ali: 3
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "metin" is null
at IzlemeOrnegi.uzunluk(IzlemeOrnegi.java:3)
at IzlemeOrnegi.yazdir(IzlemeOrnegi.java:6)
at IzlemeOrnegi.main(IzlemeOrnegi.java:10)İzleme Listesi
İstisna Yönetiminde İyi Uygulamalar
Mümkünse catch (Exception e) yerine beklenen türü yakalayın; her türe uygun tepki verin.
Boş catch { } hatayı gizler. En azından kaydedin (log) veya kullanıcıya bildirin.
Dosya, bağlantı gibi kaynaklar için try-with-resources veya finally kullanın.
null, sınır ve sıfır denetimi yapın; RuntimeException yakalamak yerine kodu düzeltin.
Döngüden çıkmak gibi olağan işler için istisna fırlatmayın; istisnalar istisnai durumlar içindir.
Mesaj hatalı değeri ve beklentiyi söylesin: "Not 0-100 arası olmalı: 120".
Çözebileceğiniz yerde yakalayın; çözemiyorsanız throws ile iletin.
İstisnaları bir dosyaya kaydetmek (logging), sonradan hatanın izini sürmeyi kolaylaştırır.
İzleme Listesi
final, finally ve finalize
| Ne? | Görevi | |
|---|---|---|
final | Anahtar kelime | Değişken: yeniden atanamaz · metot: geçersiz kılınamaz · sınıf: alt sınıfı olamaz |
finally | Anahtar kelime (blok) | try'dan sonra, istisna olsun olmasın her durumda çalışan temizlik bloğu |
finalize() | Object sınıfının metodu | Çöp toplayıcı nesneyi silmeden önce çağırabilirdi. Ne zaman çağrılacağı belirsizdir; Java 9'dan beri kullanımdan kaldırılmış (deprecated) durumdadır. |
finalize() değil, try-with-resources veya finally kullanılır.Özet
Özet
| Kavram | Özü |
|---|---|
| İstisna | Çalışma zamanında normal akışı bozan durum; türü, mesajı ve yeri olan bir nesne |
try / catch | Riskli kod try'da; eşleşen ilk catch çalışır, try'ın kalanı atlanır |
| catch sırası | Alt sınıf önce, üst sınıf sonra; tersi derleme hatası. A | B (Java 7+) |
finally | Her durumda çalışır, return'den bile önce; temizlik için |
| try-with-resources | try (Kaynak k = …): AutoCloseable kaynak otomatik kapanır |
| Hiyerarşi | Throwable → Error | Exception → … RuntimeException |
| Kontrol edilen | Exception (Runtime hariç): ele al veya throws ile bildir |
| Kontrol edilmeyen | RuntimeException, Error: zorunluluk yok; önle |
throw / throws | Fırlat (gövdede, nesne) / bildir (imzada, türler) |
| Yayılım | Yakalanmayan istisna çağıran metoda geçer; main de yakalamazsa program sonlanır |
| Özel istisna | class X extends Exception + super(mesaj) |
| İzleme listesi | Tür + mesaj, sonra çağrı zinciri: ilk at satırı istisnanın doğduğu yer |
Özet
Sık Yapılan Hatalar
new FileReader(ad), try/throws yok: unreported exception FileNotFoundException; must be caught or declared to be thrown.
catch (Exception e), sonra catch (ArithmeticException e): exception ArithmeticException has already been caught.
Dosya işlemi olmayan try'a catch (FileNotFoundException e): exception FileNotFoundException is never thrown in body of corresponding try statement.
catch veya finally olmayan try: 'try' without 'catch', 'finally' or resource declarations.
Aynı blokta throw'un ardından gelen satır: unreachable statement.
try içinde tanımlanan sonuc sonra yazdırılırsa: cannot find symbol. Try'dan önce tanımlayın.
catch (Exception e) { } derlenir ama hata iz bırakmadan kaybolur.
throw "hata"; → incompatible types: String cannot be converted to Throwable.
Özet
Örnek Problemler (1)
Problem 1: Çıktı nedir?
static int f() { try { System.out.print("A"); int x = 5 / 0; System.out.print("B"); return 1; } catch (ArithmeticException e) { System.out.print("C"); return 2; } finally { System.out.print("D"); } } // main içinde System.out.println(" " + f());
Problem 2: Çıktı nedir?
try { String s = "12a"; int n = Integer.parseInt(s); System.out.println("Sayı: " + n); } catch (IllegalArgumentException e) { System.out.println("IAE"); } catch (Exception e) { System.out.println("Exception"); }
Problem 3
Problem 2'de iki catch bloğunun yeri değiştirilirse ne olur?
Cevapları göster
ACD 2: “A”; bölmede istisna (B vereturn 1atlanır); catch “C” yazar, 2'yi hazırlar; finally “D” yazar; 2 döner.IAE:NumberFormatException,IllegalArgumentException'ın alt sınıfıdır.- Derleme hatası:
exception IllegalArgumentException has already been caught.
Özet
Örnek Problemler (2)
Problem 4: Çıktı nedir?
static void a() { System.out.print("a1 "); b(); System.out.print("a2 "); } static void b() { System.out.print("b1 "); throw new IllegalStateException("!"); } // main içinde try { a(); System.out.print("m "); } catch (IllegalStateException e) { System.out.print("yakalandı" + e.getMessage()); } finally { System.out.println(" son"); }
İstisna b()'de doğuyor; b() ve a()'da try yok. Hangi print'ler çalışır, hangileri atlanır? finally ne zaman çalışır?
Cevabı göster
a1 b1 yakalandı! son
İstisna b → a → main yolunu izler: “a2” ve “m” atlanır. main'deki catch yakalar, ardından finally “ son” yazar ve satırı bitirir.
Özet
Örnek Problemler (3)
Problem 5: toplam kaçtır?
int[] d = {4, 0, 2}; int toplam = 0; for (int i = 0; i <= d.length; i++) { try { toplam += 12 / d[i]; } catch (ArithmeticException e) { toplam += 100; } catch (ArrayIndexOutOfBoundsException e) { toplam += 1000; } } System.out.println(toplam);
Problem 6: Çıktı nedir?
try { throw new RuntimeException("X"); } finally { System.out.println("F"); }
Cevapları göster
- 1109: 12/4 = 3, 12/0 → +100, 12/2 = 6,
d[3]→ +1000. Her tur kendi try'ı ile korunduğu için döngü sürer. - Önce F, ardından
Exception in thread "main" java.lang.RuntimeException: X: finally çalışır ama istisna yakalanmadığı için program sonlanır.
Özet
Alıştırmalar (1)
- Metni yaşa çeviren
int yasOku(String metin)yazın: sayı değilseNumberFormatExceptiondoğal olarak oluşsun, negatifseIllegalArgumentExceptionfırlatın."20","-3","yirmi"girdileri için iki catch ile mesaj yazdırın. GecersizNotHatasiadlı kontrol edilen bir istisna ve not 0–100 dışındaysa onu fırlatannotGir(int not)yazın.- 1. alıştırmada catch sırası
IllegalArgumentException, sonraNumberFormatExceptionolursa ne olur?
Cevaplar / ipuçları
int yas = Integer.parseInt(metin); if (yas < 0) throw new IllegalArgumentException("Yaş negatif: " + yas); return yas;· Çıktı:Yaş: 20,Yaş negatif: -3,Sayı değil: yirmi. NFE catch'i önce yazılmalı.class GecersizNotHatasi extends Exception { … super(mesaj); }·void notGir(int not) throws GecersizNotHatasi { if (not < 0 || not > 100) throw new GecersizNotHatasi("Not 0-100 arası olmalı: " + not); … }·notGir(120)→Not 0-100 arası olmalı: 120.- Derleme hatası:
exception NumberFormatException has already been caught(NFE, IAE'nin alt sınıfı).
Özet
Alıştırmalar (2)
- Sınıflandırın (kontrol edilen / edilmeyen):
IOException,NumberFormatException,SQLException,NullPointerException,FileNotFoundException,ClassCastException,StackOverflowError. - Bir
BufferedReader'ıfinallyile kapatan kodu try-with-resources ile yeniden yazın. double ortalama(int[] notlar)metodu boş dizi için ne yapmalı?0mı döndürmeli, istisna mı fırlatmalı? Hangi istisna?
Cevaplar / ipuçları
- Kontrol edilen:
IOException,SQLException,FileNotFoundException· edilmeyen:NumberFormatException,NullPointerException,ClassCastException,StackOverflowError(Error). try (BufferedReader r = new BufferedReader(new FileReader(yol))) { … } catch (IOException e) { … }:close()otomatik çağrılır.- 0 geçerli bir ortalamayla karışır (−1 dönüş kodu gibi). Boş dizi geçersiz bir argümandır:
throw new IllegalArgumentException("Dizi boş");
Özet
Kaynaklar
- Oracle, The Java Tutorials: Lesson: Exceptions (Catching and Handling Exceptions; The try-with-resources Statement; Unchecked Exceptions — The Controversy).
- J. Gosling ve diğ., The Java Language Specification, Java SE 21 Edition, Bölüm 11: Exceptions; 14.20 The try statement.
- Oracle, Java SE 21 API Documentation:
java.lang.Throwable,Exception,RuntimeException,Error. - P. Deitel ve H. Deitel, Java: How to Program, 11. baskı, Pearson (Bölüm 11: Exception Handling: A Deeper Look).
- K. Sierra, B. Bates ve T. Gee, Head First Java, 3. baskı, O'Reilly (Risky Behavior: exception handling).
- C. S. Horstmann, Core Java, Volume I: Fundamentals, 12. baskı, Pearson (Bölüm 7: Exceptions, Assertions, and Logging).
- J. Bloch, Effective Java, 3. baskı, Addison-Wesley (Bölüm 10: Exceptions, Madde 69–77).