Olağan Dışı Durumların Değerlendirilmesi

Olağan Dışı Durumların Değerlendirilmesi

En üst düzey geliştiricilerin bile zaman zaman hatalı kod yazabildiğini biliyoruz.
Bir programın çalışması esnasında normalde karşılaşılmaması gereken bir durum oluşursa, sektörde buna olağan dışı durum (exception) ve bu durumda ne yapılacağının belirlenmesine de olağan dışı durum yönetimi (exception handling) denir.
Bir bölme işleminde paydanın olması, beklenmeyen ya da olağan dışı bir durumdur. Aynı şekilde bir dosyaya erişim yapmak isteyen bir komutun o dosyayı bulamaması da olağan dışı bir durumdur.
C++ diline kadar, olağan dışı durumların tespiti ve yönetimi yazılımcıların özel olarak geliştirdikleri kod parçalarıyla yapılabiliyordu. C++ dilinden itibaren olağan dışı durum yönetimi, dilin içine eklenen özel komut, sınıf ve metotlarla yapılabiliyor. Java ile birlikte, Microsoft Visual Studio.Net’in üç temel dili olan Visual Basic.netC#.net ve C++.net’te olağan dışı durum yönetimi, try / catch / finally yapısı ve ilgili sınıf ve metotlarla gerçekleştirilebiliyor.

try/catch/finally Yapısı

try/catch/finally yapısının kullanılışı şöyledir:

try
{
    //hesaplanmak istenen ifade        
}
catch            
{
    //Bir hata türü tespit edilince verilmesi gereken mesaj
}            
catch            
{
    //başka Bir hata türü tespit edilince verilmesi gereken mesaj
}            
finally
{
    //her durumda çalıştırılacak olan kod parçası
}
Yukarıdaki yapıyı şöyle açıklayabiliriz:
try bloğu içinde hesaplanacak ifade yer alır. Bu ifadenin hesaplanmasında bir hata oluşmamışsacatch blokları atlanarak programın çalışması finally bloğu ile devam eder ve daha sonra programın bu bloğu izleyen kısmına geçilir.
try bloğu içindeki işlemde bir hata oluşmuşsacatch bloklarından hangisi bu hatayı algılayabiliyorsa o catch bloğu içine girilir ve gerekli hata mesajı yazdırılır. Daha sonra program finally bloğu ile yukarıda açıklandığı biçimde çalışmaya devam eder.

NOT: finally bloğu ne olursa olsun çalışacağından burada genellikle try bloğu içinde bellek hatalarına (memory leak gibi) ya da açık kalmış bağlantılara yol açabilecek değişkenler yok edilri.
Şimdi basit bir örnekle try/catch bloklarını açıklayalım:
public class Main {
    public static void main(String[] args) {
        try {
            int a = 42 / 0;
        } catch (ArithmeticException MatematikselHata) {
            System.out.println(" İşlem yapılırken matematiksel bir hata oluştu :" + MatematikselHata.getMessage());
        }
    }
}
Burada ArithmeticException programda herhangi bir aritmetiksel hata olduğunda sistemin yanıtıdır. Örnek kodumuzda ArithmeticException Matematiksel hata olarak aktarılmış bu da dışarıya output olarak verilmiştir.
try/catch/finally yapısında kullanırken alınabilecek exception türleri aşağıdadır. Yapılan programa göre hangi hata durumlarında programınızın nasıl tepki vereceğine karar verebilirsiniz.

Örnek Exception Türleri
Hata TipleriHatanın Anlamı
ArithmeticExceptionAritmatiksel bir işlem sırasında oluşan hata 
ArrayIndexOutOfBoundsExceptionArray sınırlarından çıkılma hatası
ArrayStoreExceptionArray yapısına uymayan bir değer kaydedilmeye çalışıldığında
ClassCastExceptionUygunsuz class atama işlemi
IllegalArgumentExceptionUygun olmayan argüman kullanımı
IllegalMonitorStateExceptionUygun olmayan monitör işlemi
IllegalStateExceptionSistemin uygun pozisyonda olmadığını belirtir
IllegalThreadStateExceptionTread durumunun uygun olmadığını belirtir
IndexOutOfBoundsExceptionIndex'in sınırlardan çıkılma hatası
NegativeArraySizeExceptionArray'in boyutuna negatif değer verilmiş olması hatası
NullPointerExceptionBoş pointer hatası
NumberFormatExceptionUygun olmayan sayı formatı hatası
SecurityExceptionGüvenlik hatası
StringIndexOutOfBoundsString yapısının sınırlarından çıkma hatası
UnsupportedOperationExceptionDesteklenmeyen işlem hatası
ClassNotFoundExceptionClass bulunmama hatası
CloneNotSupportedExceptionÇoğalmaya çalışılan bir objenin çoğalamayacağını belirten hata
IllegalAccessExceptionUygunsuz erişim hatası
InstantiationExceptionBir objenin oluşturulması esnasında oluşan hata
InterruptedExceptionBir tread'in diğer tread'i durdurma hatası
NoSuchFieldExceptionAranılan alanın olmadığı hatası
NoSuchMethodExceptionKıllanılan methodun bulunmama hatası
Şimdi  başka bir örneğe göz atalım:

package com.turkcell.and101;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class ExceptionOrnek1 {
    public static void main(String[] args) {

        String str = "Bunu dosyaya yazdir";
        File file = new File("dosya.txt");
        FileWriter fileWriter = null;

        try {
            fileWriter = new FileWriter(file, false);
            fileWriter.write(str);
        }
        catch (IOException dosyaHatasi) {
            dosyaHatasi.printStackTrace();
        }
        finally {
            try {
                if (fileWriter != null)
                    fileWriter.close();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
Yukarıda basit bir dosya okuma işlemi görüntülenmektedir. Burada fileWriter değişkeni bir dosyaya erişim açar ve write komutu ile str değişkeni dosyanın içerisine yazılır. write komutu diske yazma yapamaması durumunda bir IOException (Input Output - Giriş Çıkış) hatası fırlatır ve biz de bunu catch bloğu içerisinde yakalarız.
NOT: printStackTrace metodu hatanın detaylı bir şekilde konsola yazılmasını sağlar.
catch bloğu içerisinde yazma işlemi gerçekleşmese bile dosya ile erişimin devam etmesi ihtimali programımızın ciddi bir soruna yola açmasını sağlayabilir. Bu yüzden dosya yazma işlemi olmasa da bizim dosya bağlantısını mutlaka kapatmamız gerekir. İşte bu yüzden finally bloğu içerisinde close metodunu çalıştırırız ve eğer yazma işlemi gerçekleşmese de dosya ile bağlantıyı kesmiş oluruz. Burada null kontrolü yapılmasının sebebi fileWriter değişkeninin null olabilme ihtimalidir.
NOT: Dosya yazma ile ilgili geniş bilgi bir sonraki bölümde anlatılacaktır.

Kendi hatalarımızı oluşturma

Program içerisinde kendi hazırladığımız sınıf ve metodlar zaman zaman bize özgü hatalar fırlatabilirler. Bunu sağlamak için kendimize ait bir hata sınıfı oluşturabiliriz. Java Exception sınıfı extend edilebilir bir sınıf olduğundan aşağıdaki gibi bir hata sınıfı hazırlanabilir:
package com.turkcell.and101;

public class OzelException extends Exception {
    private static final long serialVersionUID = 1L;

    @Override
    public String getMessage() {
        return "Benim hatam olustu.";
    }
}
Yukarıdaki örnekte MyException adında bir hata sınıfı oluşturduk ve getMessage metodunu değiştirdik. Şimdi bu hatayı fırlatan bir metod hazırlayalım ve uygulamada bu hatayı yakalayalım:
package com.turkcell.and101;

public class ExceptionOrnek2 {
    public static void main(String[] args) {
        try {
            hataFirlatir();
        }
        catch (OzelException e) {
            System.out.println(e.getMessage());
        }
    }

    public static void hataFirlatir() throws OzelException {
        throw new OzelException();
    }
}

Hazırladığımız hataFirlatir adlı metod az önce oluşturduğumuz OzelException hatasını throw komutuyla ile fırlatıyor. Derleyici ise bu metodun bir hata fırlattığını throw sözcüğüyle anlıyor. main metodu içinde hataFirlatir çağırıldığında OzelException hatasının mutlaka yakalanması gerekiyor ve getMessage metodu konsola  “Benim hatam oluştu” mesajını veriyor.
Profesyonel uygulamaların çoğunda, hazırlanan servisler kullanılırken bir hata oluştuğunda bunu diğer sınıflara belirtmek için özel hata sınıfları hazırlanır. Bu konuya diğer bölümlerde tekrar değineceğiz.

Yorumlar

Bu blogdaki popüler yayınlar

İç İçe Döngüler

CSS Bir Elemanın Genişliği ve Yüksekliği

JavaScript Dilinde Fonksiyon Çağırma Teknikleri