Ders İçeriği

Java programlama dilinde, programın normal akışını bozan, beklenmedik olaylara istisna (exception) denir. İstisnalar, programın çökmesini veya hatalı sonuçlar üretmesini engelleyerek, daha sağlam ve güvenilir uygulamalar geliştirmemizi sağlar. Java, istisnaları yönetmek için güçlü bir mekanizma sunar.

İstisna Nedir?

İstisna, bir programın çalışması sırasında meydana gelen ve programın normal akışını kesintiye uğratan bir olaydır. Bu olaylar genellikle hatalardan kaynaklanır, ancak her hata bir istisna değildir. Örneğin, bir dosya okumaya çalışırken dosyanın bulunamaması, bir sayı sıfıra bölünmeye çalışılması veya bir dizinin sınırları dışına erişilmeye çalışılması istisnalara yol açabilir.

Java'da istisnalar, java.lang.Throwable sınıfından türeyen nesnelerdir. Throwable sınıfının iki ana alt sınıfı vardır:

  1. Error: Genellikle programın kontrolü dışındaki ciddi sorunları temsil eder (örneğin, OutOfMemoryErrorStackOverflowError). Bu tür hatalar genellikle programcı tarafından yakalanıp düzeltilemez ve uygulamanın sonlandırılmasına neden olur.
  2. Exception: Programcı tarafından yakalanıp yönetilebilecek daha az ciddi sorunları temsil eder. Exception sınıfının da iki ana alt kategorisi vardır:
    • Kontrollü İstisnalar (Checked Exceptions): Derleme zamanında kontrol edilen istisnalardır. Bu istisnalar, metot imzasında throws anahtar kelimesiyle belirtilmeli veya try-catch bloğu içinde yakalanmalıdır. Aksi takdirde derleme hatası alırsınız. Örnekler: IOExceptionSQLExceptionFileNotFoundException.
    • Kontrolsüz İstisnalar (Unchecked Exceptions - Runtime Exceptions): Çalışma zamanında meydana gelen istisnalardır ve derleme zamanında kontrol edilmezler. Programcı tarafından yakalanmaları zorunlu değildir, ancak iyi bir uygulama için yakalanmaları önerilir. Genellikle programlama hatalarından kaynaklanırlar. Örnekler: NullPointerExceptionArrayIndexOutOfBoundsExceptionArithmeticException.

İstisna Yönetimi Mekanizmaları

Java'da istisnaları yönetmek için try-catch-finally blokları ve throws anahtar kelimesi kullanılır.

try-catch Bloğu

try bloğu, istisna potansiyeli olan kodu içerir. Eğer try bloğu içinde bir istisna meydana gelirse, kontrol hemen ilgili catch bloğuna geçer. catch bloğu, belirli bir istisna türünü yakalamak ve bu istisnayı işlemek için kullanılır.

public class IstisnaOrnek {
    public static void main(String[] args) {
        try {
            // İstisna potansiyeli olan kod
            int sonuc = 10 / 0; // ArithmeticException fırlatır
            System.out.println("Sonuç: " + sonuc);
        } catch (ArithmeticException e) {
            // İstisna yakalandığında çalışacak kod
            System.out.println("Hata: Sıfıra bölme hatası oluştu!");
            System.out.println("Hata mesajı: " + e.getMessage());
            e.printStackTrace(); // İstisnanın yığın izini yazdırır
        } finally {
            // İsteğe bağlı: İstisna oluşsa da oluşmasa da her zaman çalışacak kod
            System.out.println("Try-catch bloğu tamamlandı.");
        }
        System.out.println("Program devam ediyor...");
    }
}

Çıktı:

Hata: Sıfıra bölme hatası oluştu!
Hata mesajı: / by zero
java.lang.ArithmeticException: / by zero
    at IstisnaOrnek.main(IstisnaOrnek.java:6)
Try-catch bloğu tamamlandı.
Program devam ediyor...
  • Birden fazla catch bloğu kullanarak farklı istisna türlerini yakalayabilirsiniz. İstisnalar, en spesifikten en genele doğru sıralanmalıdır.

    try {
        String s = null;
        System.out.println(s.length()); // NullPointerException
        int[] dizi = new int[5];
        System.out.println(dizi[10]); // ArrayIndexOutOfBoundsException
    } catch (NullPointerException e) {
        System.out.println("Null referans hatası: " + e.getMessage());
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Dizi sınırı aşıldı hatası: " + e.getMessage());
    } catch (Exception e) { // Tüm diğer istisnaları yakalar
        System.out.println("Genel bir hata oluştu: " + e.getMessage());
    }
    

finally Bloğu

finally bloğu, try bloğundan sonra, bir istisna oluşsa da oluşmasa da her zaman yürütülen isteğe bağlı bir bloktur. Genellikle kaynakları (dosya akışları, veritabanı bağlantıları vb.) kapatmak için kullanılır.

throws Anahtar Kelimesi

Bir metot, fırlatabileceği kontrollü istisnaları metot imzasında throws anahtar kelimesiyle belirtebilir. Bu, metodu çağıranın bu istisnayı ya yakalaması ya da kendi imzasında belirtmesi gerektiğini bildirir.

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class DosyaOkuyucu {
    public void dosyaOku(String dosyaAdi) throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(dosyaAdi);
        System.out.println("Dosya başarıyla okundu.");
        // Dosya işlemleri...
    }

    public static void main(String[] args) {
        DosyaOkuyucu okuyucu = new DosyaOkuyucu();
        try {
            okuyucu.dosyaOku("olmayan_dosya.txt");
        } catch (FileNotFoundException e) {
            System.out.println("Hata: Dosya bulunamadı! " + e.getMessage());
        }
    }
}

throw Anahtar Kelimesi

throw anahtar kelimesi, programcı tarafından manuel olarak bir istisna fırlatmak için kullanılır. Genellikle belirli bir koşul oluştuğunda özel bir hata durumunu belirtmek için kullanılır.

public class YasKontrol {
    public void yasBelirle(int yas) {
        if (yas < 0) {
            throw new IllegalArgumentException("Yaş negatif olamaz!");
        } else if (yas > 120) {
            throw new IllegalArgumentException("Yaş 120'den büyük olamaz!");
        }
        System.out.println("Belirlenen yaş: " + yas);
    }

    public static void main(String[] args) {
        YasKontrol kontrol = new YasKontrol();
        try {
            kontrol.yasBelirle(-5);
        } catch (IllegalArgumentException e) {
            System.out.println("Hata: " + e.getMessage());
        }
    }
}

Özel İstisnalar Oluşturma

Java'da kendi özel istisna sınıflarınızı oluşturabilirsiniz. Bunun için Exception veya RuntimeException sınıfından türeyen yeni bir sınıf tanımlamanız yeterlidir. Kontrollü bir istisna için Exception'dan, kontrolsüz bir istisna için RuntimeException'dan türetilir.

public class YetersizBakiyeException extends Exception {
    public YetersizBakiyeException(String mesaj) {
        super(mesaj);
    }
}

public class BankaHesabi {
    private double bakiye;

    public BankaHesabi(double bakiye) {
        this.bakiye = bakiye;
    }

    public void paraCek(double miktar) throws YetersizBakiyeException {
        if (bakiye < miktar) {
            throw new YetersizBakiyeException("Hesapta yeterli bakiye yok! Mevcut bakiye: " + bakiye);
        }
        bakiye -= miktar;
        System.out.println("Para çekildi. Yeni bakiye: " + bakiye);
    }

    public static void main(String[] args) {
        BankaHesabi hesap = new BankaHesabi(500);
        try {
            hesap.paraCek(700);
        } catch (YetersizBakiyeException e) {
            System.out.println("İşlem başarısız: " + e.getMessage());
        }
    }
}

İstisna yönetimi, Java'da sağlam ve hataya dayanıklı uygulamalar geliştirmek için kritik bir konudur. Doğru istisna yönetimi stratejileriyle, programlarınızın beklenmedik durumlarla zarif bir şekilde başa çıkmasını sağlayabilirsiniz. Bir sonraki derste Dosya İşlemleri (I/O) konusunu inceleyeceğiz.