Hata Yönetimi (Exceptions)
Hiçbir program kusursuz bir dünyada çalışmaz: dosya bulunamaz, ağ kopar, kullanıcı beklenmedik veri girer, sıfıra bölünür. İyi bir yazılımcı bu durumları yok saymaz; onları öngörür ve zarifçe ele alır. Java'da bunun a…
Hata Yönetimi (Exceptions)
Hiçbir program kusursuz bir dünyada çalışmaz: dosya bulunamaz, ağ kopar, kullanıcı beklenmedik veri girer, sıfıra bölünür. İyi bir yazılımcı bu durumları yok saymaz; onları öngörür ve zarifçe ele alır. Java'da bunun aracı exception (istisna) mekanizmasıdır. Amaç, program bir sorunla karşılaştığında çökmek yerine kontrollü biçimde tepki vermesidir.
try, catch, finally
Riskli kodu bir try bloğuna koyarız; bir hata oluşursa akış ilgili catch bloğuna atlar:
try { int sonuc = 10 / 0; // ArithmeticException fırlar } catch (ArithmeticException e) { System.out.println(e.getMessage()); }
catch, yakalamak istediğin exception tipini belirtir. Hata o tipteyse blok çalışır, değilse
exception yukarı doğru "kabarır". finally bloğu ise her durumda — hata olsa da olmasa
da — çalışır; bu yüzden temizlik/kaynak kapatma işleri için idealdir.
Örnek 1 (./Ornek1.java) en sık karşılaşacağın ArithmeticException, NullPointerException
ve ArrayIndexOutOfBoundsException'ı yakalar ve finally'nin davranışını gösterir.
Checked vs unchecked
Java'da exception'lar iki büyük aileye ayrılır:
- Checked exceptions (
Exceptionsoyundan,RuntimeExceptionhariç): Derleyici bunları ele almanı zorunlu tutar. Yatry-catchile yakalarsın ya da metot imzasındathrowsile bildirirsin. Genelde dış dünyayla ilgili, öngörülebilir sorunlardır (dosya yok, ağ hatası). - Unchecked exceptions (
RuntimeExceptionsoyundan): Derleyici zorunlu tutmaz. Genelde programlama hatalarıdır (NullPointerException,IllegalArgumentException,NumberFormatException).
throw ve throws
throw bir exception'ı elle fırlatır; throws ise bir metodun hangi checked exception'ı
fırlatabileceğini bildirir:
static void paraCek(double bakiye, double tutar) throws YetersizBakiyeException { if (tutar > bakiye) throw new YetersizBakiyeException("Yetersiz bakiye"); }
Özel (custom) exception
Kendi anlamlı exception tiplerini tanımlayabilirsin. Exception'dan türetirsen checked,
RuntimeException'dan türetirsen unchecked olur. Bu, hataya iş anlamı katar:
YetersizBakiyeException, int -1 döndürmekten çok daha açıktır. Örnek 2 (./Ornek2.java)
checked/unchecked ayrımını, throw/throws'u ve özel bir exception'ı bir banka senaryosunda
gösterir.
try-with-resources
Dosya, veritabanı bağlantısı, akış (stream) gibi kaynakları işin bitince kapatmak
zorundayız. Bunu finally ile elle yapmak hataya açıktır. Java bunun için temiz bir yol
sunar: try-with-resources. Parantez içinde açtığın, AutoCloseable'ı uygulayan kaynaklar,
blok bitince (hata olsa bile) otomatik kapatılır:
try (Baglanti b = new Baglanti("db")) { b.sorguCalistir("..."); } // b.close() otomatik çağrılır
multi-catch
Birden çok exception tipini aynı şekilde ele alacaksan, tek blokta | ile birleştirebilirsin:
catch (NumberFormatException | ArithmeticException e) { ... }
Örnek 3 (./Ornek3.java) AutoCloseable bir kaynak yazar, try-with-resources ile otomatik
kapanışı (hatalı senaryo dahil) ve multi-catch'i gösterir.
İyi uygulama notları
- Boş
catchblokları yazma; hatayı en azından logla. Sessizce yutulan hata, bulunması en zor hatadır. catch (Exception e)gibi çok geniş yakalamalardan, gerçekten gerekmedikçe kaçın.- Akışı kontrol etmek için exception kullanma; exception "istisnai" durumlar içindir.
- Anlamlı mesajlar ve uygun (özel) tipler kullan.
Özet
Riskli kodu try ile sarmayı, catch ile hataya tepki vermeyi, finally ve
try-with-resources ile kaynakları güvenle kapatmayı öğrendik. Checked/unchecked ayrımını,
throw/throws'u ve özel exception'ları gördük. Artık programların hata karşısında
çökmesini değil, kontrollü davranmasını sağlayabilirsin. Sırada, çok sayıda veriyi yönetmenin
güçlü yolu: Collections Framework.
▶ Kod Örnekleri(3)
Ornek1
çalıştırılabilir1// Ornek1: try-catch-finally ve yaygın exception türleri.
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5 public static void main(String[] args) {
6 // --- try-catch: hatayı yakala, program çökmesin ---
7 try {
8 int sonuc = 10 / 0; // ArithmeticException fırlatır
9 System.out.println(sonuc);
10 } catch (ArithmeticException e) {
11 System.out.println("Yakalandı (aritmetik): " + e.getMessage());
12 }
13
14 // --- NullPointerException ---
15 try {
16 String s = null;
17 s.length(); // null üzerinde metot çağrısı
18 } catch (NullPointerException e) {
19 System.out.println("Yakalandı (null): null bir nesnenin metodu çağrıldı.");
20 }
21
22 // --- ArrayIndexOutOfBoundsException ---
23 try {
24 int[] dizi = {1, 2, 3};
25 System.out.println(dizi[5]); // geçersiz indeks
26 } catch (ArrayIndexOutOfBoundsException e) {
27 System.out.println("Yakalandı (indeks): dizi sınırı aşıldı -> " + e.getMessage());
28 }
29
30 // --- finally: hata olsa da olmasa da HER ZAMAN çalışır ---
31 // Kaynak kapatma / temizlik için idealdir.
32 try {
33 System.out.println("\ntry bloğu çalışıyor...");
34 throw new RuntimeException("örnek hata");
35 } catch (RuntimeException e) {
36 System.out.println("catch: " + e.getMessage());
37 } finally {
38 System.out.println("finally: temizlik yapıldı (her durumda çalışır).");
39 }
40
41 System.out.println("\nProgram çökmeden devam etti.");
42 }
43}Ornek2
çalıştırılabilir1// Ornek2: checked/unchecked, throw/throws ve özel (custom) exception.
2// Çalıştırma: java Ornek2.java
3public class Ornek2 {
4
5 // throws: bu metot bir checked exception fırlatabilir, çağıran ilgilenmeli.
6 static void paraCek(double bakiye, double tutar) throws YetersizBakiyeException {
7 if (tutar > bakiye) {
8 // throw: bir exception nesnesini elle fırlat.
9 throw new YetersizBakiyeException(
10 "Yetersiz bakiye: istenen " + tutar + ", mevcut " + bakiye);
11 }
12 System.out.println(tutar + " TL çekildi. Kalan: " + (bakiye - tutar));
13 }
14
15 public static void main(String[] args) {
16 double bakiye = 500;
17
18 // Checked exception derleyici tarafından zorunlu kılınır: ya yakala ya da bildir.
19 try {
20 paraCek(bakiye, 200);
21 paraCek(bakiye, 800); // bu satır YetersizBakiyeException fırlatır
22 } catch (YetersizBakiyeException e) {
23 System.out.println("İşlem reddedildi: " + e.getMessage());
24 }
25
26 // Unchecked (RuntimeException) yakalamak zorunlu değildir ama yakalanabilir.
27 try {
28 int x = Integer.parseInt("abc"); // NumberFormatException (unchecked)
29 System.out.println(x);
30 } catch (NumberFormatException e) {
31 System.out.println("Sayı çevrilemedi: geçersiz format.");
32 }
33 }
34}
35
36// Özel checked exception: Exception'dan türetilir.
37// (RuntimeException'dan türetseydik unchecked olurdu.)
38class YetersizBakiyeException extends Exception {
39 public YetersizBakiyeException(String mesaj) {
40 super(mesaj);
41 }
42}Ornek3
çalıştırılabilir1// Ornek3: try-with-resources, AutoCloseable ve multi-catch.
2// Çalıştırma: java Ornek3.java
3public class Ornek3 {
4
5 public static void main(String[] args) {
6 // --- try-with-resources ---
7 // Parantez içinde açılan kaynaklar, blok bitince (hata olsa bile)
8 // OTOMATİK kapatılır. Kaynak, AutoCloseable'ı uygulamalıdır.
9 System.out.println("--- Normal akış ---");
10 try (Baglanti b = new Baglanti("veritabani")) {
11 b.sorguCalistir("SELECT * FROM urun");
12 }
13
14 System.out.println("\n--- Hata olsa bile kapatılır ---");
15 try (Baglanti b = new Baglanti("dosya")) {
16 b.sorguCalistir("HATALI");
17 } catch (RuntimeException e) {
18 System.out.println("Yakalandı: " + e.getMessage());
19 }
20
21 // --- multi-catch: birden çok exception'ı tek blokta yakala ---
22 System.out.println("\n--- multi-catch ---");
23 for (String girdi : new String[]{"10", "abc"}) {
24 try {
25 int n = Integer.parseInt(girdi);
26 System.out.println("100 / " + n + " = " + (100 / n));
27 } catch (NumberFormatException | ArithmeticException e) {
28 System.out.println("'" + girdi + "' için hata: " + e.getClass().getSimpleName());
29 }
30 }
31 }
32}
33
34// AutoCloseable: try-with-resources tarafından otomatik kapatılabilen kaynak.
35class Baglanti implements AutoCloseable {
36 private final String ad;
37
38 Baglanti(String ad) {
39 this.ad = ad;
40 System.out.println("[açıldı] " + ad);
41 }
42
43 void sorguCalistir(String sorgu) {
44 if (sorgu.equals("HATALI")) {
45 throw new RuntimeException("sorgu çalıştırılamadı");
46 }
47 System.out.println("[sorgu] " + sorgu);
48 }
49
50 @Override
51 public void close() { // blok bitince otomatik çağrılır
52 System.out.println("[kapandı] " + ad);
53 }
54}