NESNE YÖNELİMLİ PROGRAMLAMA HAFTA # 10
Konular Kural Dışı Durumlar try ve catch Blokları ve throw Komutu Kural Dışı Durum Sınıfı Tanımlama Bir try Bloğuyla Çok Sayıda catch Kullanımı İç İçe try - catch Blokları finally Bloğu
Kural Dışı Durumlar Programlar genellikle girişlerin kullanıcı tarafından uygun girileceği veya çalışmasının normal şekilde tamamlanacağı varsayılarak yazılır. Java da program istenmeyen bir durum oluştuğunda durumu dışarıya bildirir. Programcı Java da bulunan istenmeyen durum çözme araçlarını kullanarak daha hatasız bir program yazabilir. Bu tür araçların kullanımı programı daha anlaşılabilir yapar ve hata denetimini kolaylaştırır.
Kod derlenebilir Kod hatasızdır Derleme sadece sözdizimi kontrolü yapar Kod hatasız Program hatasız çalışacak Program çalışması kontrol dışıdır Hata hata Hatalara gerektiği gibi davranmak gerekir Tüm bunlar kontrollü olmalıdır
İstisna (exception) Nedir? İstisna, bir kod dizisinde, çalışma sırasında ortaya çıkan, anormal bir durumdur. İstisna, hatalı olsun veya olmasın, donanım veya yazılım tarafından tespit edilebilir, olağan olmayan herhangi bir olaydır ve özel bir işlem gerektirir Bir çalışma zamanı (run-time) hatasıdır. İstisnalar, programcılara, hatalar karşısında istenildiği şekilde davranabilme ve oluşacak hataları kontrol altına alabilme yeteneği ve esnekliği sağlar. En önemli kazanım ise hata kontrolü ile algoritmanın birbirinden ayrılmasıdır.
Bir sistemi tamamen istisnalara karşı korunaklı tasarlamak ve oluşturmak çok zordur. Çıkabilecek sorunların önceden tamamıyla düşünülmesi mümkün değildir. Sorunlar ciddi farklılıklar gösterebilir. Veri tutarsızlığı Operatör hatası Bellek hatası Yanlış girdi Donanımsal tutarsızlık Sistemlerin tamamen çökmesinin veya güvenlik problemleriyle karşılaşmalarının %80 oranında istisnalardan kaynaklandığı bilinmektedir.
İstisna Oluşturma İstisna oluşumuna en basit örnek olarak, yanlış kullanılmış dizi uygulamasını verebiliriz. Java programlama dilinde dizilere erişim her zaman kontrollüdür. Java programlama dilinde dizilerin içerisine bir eleman atmak istiyorsak veya var olan bir elemana ulaşmak istiyorsak, bu işlemlerin hepsi Java tarafından önce bir kontrolden geçirilir. Amaç, güvenli bir dizi erişim mekanizmasına sahip olmaktır.
İstisna Oluşturma sayi[], ilkel (primitive) int tipinde dizi değişkenidir ve bağlı bulunduğu dizi nesnesinin içerisinde 2 adet int tipinde eleman vardır. for döngüsü sayesinde dizi içerisindeki elemanlar ekrana basılmaktadır. Örnekteki hata, for döngüsünün fazla dönmesiyle dizinin olmayan elemanına ulaşmak istememizden kaynaklanmaktadır. Böyle bir hareket, çalışma-anında (run-time) hata oluşmasına sebebiyet verip uygulamayı aniden sonlandıracaktır. Ekran çıktısı: Buradaki istisna, ArrayIndexOutOfBoundsException istisnasıdır. Bu istisnanın sebebi, bir dizinin olmayan elemanına erişmeye çalışmamızdır.
İstisna Oluşma Sebepleri Açmak istediğiniz fiziksel dosya yerinde olmayabilir. Uygulamanıza kullanıcılar tarafında, beklenmedik bir girdi kümesi gelebilir. Ağ bağlantısı kopmuş olabilir. Yazmak istediğiniz dosya, başkası tarafından açılmış olduğundan yazma hakkınız olmayabilir.
İstisna yöneticisi (exception handler) İstisnanın tespitinden sonra gerekli olan özel işleme İstisna Yönetimi (exception handling) denir İstisna yönetimi kodu istisna yöneticisi (exception handler) olarak adlandırılır İstisna yöneticileri farklı istisnalar için farklı biçimlerde davranırlar. Örneğin, bir dosya sonu kontrolündeki program gereksinimlerinin sıfıra bölme işlemiyle karşılaşıldığında aynı davranışı göstermesi beklenemez. Kullanılan dilin istisna işlemini desteklemesi bu tip sorunları çok daha hızlı ve programın güvenilirliğine zarar vermeden çözebilme yeteneğini sunmaktadır.
İstisna yöneticisi (exception handler) Yazmakta olduğumuz bir programda yüzden fazla yerde dosya sonu problemi ve bir o kadar da sıfıra bölme problemi olduğunu düşünelim. Yapısal dillerde tüm bu problemler algoritma içerisine gömülü olarak yazılan kod parçalarıyla kontrol altına alınmalıdır. Bu da iki yüz defa aynı kontrolün yazılması anlamına gelebilir. Oysa istisna işleme sayesinde programın bu tip hatalarla karşılaştığında davranışının ne olacağı sadece bir istisna işleyici ile belirlenmektedir. Bu istisna işleyici birden çok program birimi tarafından kullanılabilir; bu sayede kodun hantallaşması önlendiği gibi güvenilirlik azami şekilde sağlıklı kılınmaktadır.
İstisna türleri
Tüm istisnalar, yerleşik Throwable sınıfının soyundan olan sınıfların nesneleridir. Throwable ın hemen altında, istisnaları iki ayrı dala ayıran, iki altsınıf vardır: 1. Exception Kullanıcı programlarının yakalaması gereken istisnai durumlar için kullanılır. Öntanımlı iki altsınıfı vardır, IOException RuntimeException (örn., ArrayIndexOutOfBoundsException ve NullPointerException) 2. Error Normal şartlar altında program tarafından yakalanmayacak istisnaları tanımlayan sınıftır. Error tipindeki istisnalar, Java run-time ortamının kendisi ile ilgili hatalarını göstermek için Java run-time sistemi tarafından kullanılır.
İstisna Tip Hiyerarşisi A.B.Altıntaş - Java Programlama Dili Yazılım Tasarımı
Tüm istisnaların kalıtımlandığı Throwable sınıfı, oluşan istisna hakkında bilgi döndürmek için kullanılan, iki tane metot içerir: getmessage() istisna hakkında text olarak bir bilgi döndürür. printstacktrace() bu istisnaya kadar ki çağırma yığınlarını - hangi metotlar çağrılmıştır bilgisini - döndürür.
Hata Yönetimi vs. İstisna Yönetimi Hatalara karşı programcıya düşen temel görev programının bu hatalardan dolayı tamamen çökmesini engellemektir. Programcı oluşan bu hataları program içerisinde çözmeye kalkışmamalıdır. Aslında Error sınıfından oluşan nesnelerin esas olarak yaptıkları şey programın akışını durdurup, sorunu belirtmek ve programdan çıkmaktır. Programcının bu hataları işlemesine gerek kalmadan sistem zaten bu hataları ele almaktadır. Programcının asıl yapması gereken iş çeşitli istisnaları sorun olmaktan çıkarmaya uğraşmaktır. Çalışma zamanı istisnaları genel olarak kod yazılımının yol açtığı hatalardır. Bu yüzden, programcı kendi hatalarını ele almasını sağlayacak istisna işleme teknikleri yaratmalıdır.
İstisna Yönetimi Bir Java istisnası, kod parçasının çalışma zamanında meydana gelen istisnai bir durumu tarif eden nesnedir. Ana mantık şu şekildedir: İstisnai bir durum ortaya çıktığında, o istisnayı temsil eden bir nesne yaratılır ve hataya sebep olan metodun içine fırlatılır (throw). Programcının olaya nasıl bakması gerektiğiyle ilgili olarak bu metot istisnayı ya yakalar (catch) ve işler ya da yakalanıp işlenmesi için istisnaya dokunmaz ve geçer. Java da istisna işleme konusunda beş anahtar sözcük karşımıza çıkmaktadır: try catch throw throws finally
Java da istisna yönetim bloğu aşağıdaki şekildedir: try code(); catch (exception 1) NecessaryErrorProcess1();... catch (exception N) NecessaryErrorProcessN(); finally Finally();
Örnek import javax.swing.joptionpane; class OrnekIstisnaUygulamasi public static void main(string args[]) int a,b; try a=integer.parseint (JOptionPane.showInputDialog ( lütfen integer bir sayı giriniz )); b=100/a; System.out.println( istisna sonrasi mesaj ); catch (ArithmeticException e) System.out.println( a= +a+ oldugu icin bolme islemini gerceklestiremiyoruz! ); System.out.println( yönetim sonrasi mesaj ); girdi kutusuna 0 değeri girilince program çıktısı: a=0 oldugu icin bolme islemini gerceklestiremiyoruz yönetim sonrasi mesaj 2 değeri girilince program çıktısı: istisna sonrasi mesaj yönetim sonrasi mesaj
Örnekte iki sayıyı birbirine bölen program verilmiştir. import java.util.scanner; public class Bolme public static void main(string [] args) String yanit; do System.out.print("Bolunecek sayi:\t"); Scanner klavye = new Scanner(System.in); int a = klavye.nextint(); System.out.print("Bolen sayi:\t"); int b = klavye.nextint(); int c = a / b; System.out.println(); System.out.println(a + " / " + b + " = " + c); System.out.println(); System.out.print("Bir daha denemek ister misin? (e/h) "); yanit = klavye.next(); System.out.println(); while ((yanit.equals("e")) (yanit.equals("e")));
Örnekte farklı değerler için bölme sonuçları verilmiştir. Çıktı: Bolunecek sayi: 14 Bolen sayi: 6 14 / 6 = 2 Bir daha denemek ister misin? (e/h) h Çıktı: Bolunecek sayi: 14 Bolen sayi: 0 Exception in thread main java.lang.artihmeticexception: / by zero at Bolme.main(Bolme.java:13) Press any key to continue... Yukarıdaki mesaj kural dışı bir durumla karşılaşıldığını ve program içinde çözümünün olmadığını bildirir.
Örnek: İki sayıyı birbirine bölen programın düzeltilmiş hali. import java.util.scanner; public class Bolme2 public static void main(string [] args) String yanit; do System.out.print("Bolunecek sayi:\t"); Scanner klavye = new Scanner(System.in); int a = klavye.nextint(); System.out.print("Bolen sayi:\t"); int b = klavye.nextint(); if (b == 0) System.out.println(); System.out.println("Bolen Sifir Olamaz!"); else int c = a / b; System.out.println(); System.out.println(a + " / " + b + " = " + c);
Örnek: İki sayıyı birbirine bölen programın düzeltilmiş hali - devam System.out.println(); System.out.print("Bir daha denemek ister misin? (e/h) "); yanit = klavye.next(); System.out.println(); while ((yanit.equals("e")) (yanit.equals("e"))); Çıktı: Bolunecek sayi: 14 Bolen sayi: 0 Bolen sifir olamaz! Bir daha denemek ister misin? (e/h)
Örnek: Java araçları kullanılarak bölme programın düzeltilmiş hali import java.util.scanner; public class Bolme3 public static void main(string [] args) String yanit; do Scanner klavye = new Scanner(System.in); try System.out.print("Bolunecek sayi:\t"); int a = klavye.nextint(); System.out.print("Bolen sayi:\t"); int b = klavye.nextint(); if (b == 0) throw new Exception("Kural Disi Durum: Bolen Sifir!"); int c = a / b; System.out.println(); System.out.println(a + " / " + b + " = " + c);
Örnek: Java araçları kullanılarak bölme programın düzeltilmiş hali catch (Exception ozeldurum) System.out.println(); System.out.println(ozelDurum.getMessage()); System.out.println("Bolen Sifir Olamaz!"); System.out.println(); System.out.print("Bir daha denemek ister misin? (e/h) "); yanit = klavye.next(); System.out.println(); while ((yanit.equals("e")) (yanit.equals("e"))); try bloğu herhangi bir hata ile karşılaşınca catch bloğuna geçilir. catch bloğu içinde Hata türüne uygun mesaj yazdırılır.
Konular Kural Dışı Durumlar try ve catch Blokları ve throw Komutu Kural Dışı Durum Sınıfı Tanımlama Bir try Bloğuyla Çok Sayıda catch Kullanımı İç İçe try - catch Blokları finally Bloğu
try ve catch Blokları ve throw Komutu Java da istenmeyen durumların çözümünde try-throw-catch üçlüsü kullanılır. try Denenecek program Eğer try bloğunda istenmeyen bir durum oluşursa throw ile dışarıya bildirilir. try Denenecek program Beklenmeyen durumun bildirilmesi satır (throw) Programın devamı
try ve catch Blokları ve throw Komutu throw new Exception( kural Dışı durum: Bolen sıfır! ); Java throw komutunu görünce hemen catch bloğunu çağırır. Yukarıdaki satır aşağıdaki gibi de yazılabilir. Exception ozeldurum = new Exception( kural Dışı durum: Bolen sıfır! ); throw ozeldurum; Catch bloğu hem yakalanacak kural dışı durumu belirler ve blok içinde işlem yapılmasını sağlar.
try ve catch Blokları Bir catch kalıbı, içice yuvalanmış try blokları hariç, başka bir try bloğunun attığı istisnayı yakalayamaz. Bir istisna atıldığı zaman, program kontrolü try bloğundan catch bloğuna geçer. Herhangi bir metodun çağrılması gibi catch bloğunun çağrılması söz konusu değildir. Çalışma hiçbir zaman catch bloğundan try bloğuna dönmez. catch bloğu çalıştıktan sonra, program, try/catch kalıbının hemen ardından gelen kod parçalarıyla devam eder.
throw ve throws Program sadece Java run-time sistemi tarafından yaratılan istisnaları yakalamak zorunda değildir. throw deyimi kullanılarak istisnayı programcının atması da mümkündür. Atılacak istisna Throwable sınıfının veya bu sınıfın altsınıflarının bir nesnesi olmak zorundadır. Eğer bir metot, işleyemediği bir istisnaya neden oluyorsa, bu durumu mutlaka kendini çağıran diğer programlara bildirmelidir. Bu, metodun içerisine bir throws kalıbı sokularak yapılabilir. throws kalıbı bir metodun fırlatabileceği istisnaları listeler. Bu listenin dışında bir istisna ortaya çıkacak olursa çalışma zamanı hatasına yol açar.
Örnek - throw class OrnekIstisnaThrowUygulamasi public static void main(string args[]) try throw new ArithmeticException( 0 a bolme ); catch (ArithmeticException e) System.out.println( istisnai durum= +e); System.out.println( throw islemi sonrasi mesaj ); program çıktısı: istisnai durum= java.lang.arithmeticexception: 0 a bolme throw islemi sonrasi mesaj
Örnek - throws public class ThrowsDeneme static void firatmaornegi() throws ArithmeticException System.out.print( firlatilan istisna: "); throw new ArithmeticException("deneme"); public static void main(string args[]) try firlatmaornegi(); catch(arithmeticexception e) System.out.println("burada yakalandi => "+e); program çıktısı: firlatilan istisna: burada yakalandi => java.lang.artihmeticexception: deneme
istisna cokcalis() metodunun içerisinde oluşuyor. Oluşan istisna catch mekanizması sayesinde yakalandıktan sonra bir üst sınıfa fırlatılıyor. calis() metodunun içerisinde de aynı şekilde fırlatılan istisna, catch mekanizmasıyla yakalanıp tekrar bir üst kısıma fırlatılıyor. basla() metoduna kadar gelen istisna nesnesi burada yakalanıp içerisinde saklı bulunan bilgiler printstacktrace() metoduyla ortaya çıkartılıyor.
Uygulamanın çıktısı: İstisna basla() metodunda işlenmesine karşın nerede oluştuğu bilgisi korunmaktadır.
Konular Kural Dışı Durumlar try ve catch Blokları ve throw Komutu Kural Dışı Durum Sınıfı Tanımlama Bir try Bloğuyla Çok Sayıda catch Kullanımı İç İçe try - catch Blokları finally Bloğu
Kural Dışı Durum Sınıfı Tanımlama Java da programcı kendi kural dışı sınıfını Exception sınıfından türetebilir. Yeni kural dışı durum oluştururken kurucular en önemli kısımdır. public class SifiraBolmeHatasi extends Exception // Parametre almadan çalışır public SifiraBolmeHatasi() super("bolen Sifir!"); // Parametre alarak çalışır public SifiraBolmeHatasi(String ileti) super(ileti);
Örnek - SifiraBolmeHatasi sınıfının kullanımı import java.util.scanner; public class Bolme4 public static void main(string [] args) String yanit; do Scanner klavye = new Scanner(System.in); try System.out.print("Bolunecek sayi:\t"); int a = klavye.nextint(); System.out.print("Bolen sayi:\t"); int b = klavye.nextint(); if (b == 0) throw new SifiraBolmeHatasi("Bolen Sifir!"); int c = a / b; System.out.println(); System.out.println(a + " / " + b + " = " + c);
Örnek - SifiraBolmeHatasi sınıfının kullanımı - devam catch (SifiraBolmeHatasi ozeldurum) System.out.println(); System.out.println(ozelDurum.getMessage()); System.out.println("Bolen Sifir Olamaz!"); System.out.println(); System.out.print("Bir daha denemek ister misin? (e/h) "); yanit = klavye.next(); System.out.println(); while ((yanit.equals("e")) (yanit.equals("e")));
Konular Kural Dışı Durumlar try ve catch Blokları ve throw Komutu Kural Dışı Durum Sınıfı Tanımlama Bir try Bloğuyla Çok Sayıda catch Kullanımı İç İçe try - catch Blokları finally Bloğu
Bir try Bloğuyla Çok Sayıda catch Kullanımı Java da bir try bloğuyla birden fazla catch bloğu birlikte kullanılabilir. Java da istenmeyen durum oluştuğunda uygun ilk catch bloğunu çalıştırır. import java.util.scanner; public class Bolme5 public static void main(string [] args) String yanit; do Scanner sc = new Scanner(System.in); SifiraBolmeHatasi sifir=new SifiraBolmeHatasi("Bolen Sifir!"); BireBolmeHatasi bir = new BireBolmeHatasi("Bolen Bir!"); EksiBireBolmeHatasi eksibir=new EksiBireBolmeHatasi("Bolen Eksi Bir!"); try System.out.print("Bolunecek sayi:\t"); int a = klavye.nextint(); System.out.print("Bolen sayi:\t"); int b = klavye.nextint();
Örnek - Birden fazla catch bloğu - devam if (b == 0) throw sifir; else if (b == 1) throw bir; else if (b == -1) throw eksibir; int c = a / b; System.out.println(); System.out.println(a + " / " + b + " = " + c); catch (SifiraBolmeHatasi ozeldurum) System.out.println(); System.out.println(ozelDurum.getMessage()); System.out.println("Bolen Sifir Olamaz!"); catch (BireBolmeHatasi ozeldurum) System.out.println(); System.out.println(ozelDurum.getMessage()); System.out.println("Bolen Bir; Sonuc Sayinin Kendisi!");
Örnek - Birden fazla catch bloğu - devam catch (EksiBireBolmeHatasi ozeldurum) System.out.println(); System.out.println(ozelDurum.getMessage()); System.out.println("Bolen Eksi Bir; Sonuc Sayinin Eksisi!"); catch (Exception ozeldurum) System.out.println(); System.out.println(ozelDurum.getMessage()); System.out.println("Genel Hata Olustu"); System.out.println(); System.out.print("Bir daha denemek ister misin? (e/h) "); yanit = klavye.next(); System.out.println(); while ((yanit.equals("e")) (yanit.equals("e")));
Konular Kural Dışı Durumlar try ve catch Blokları ve throw Komutu Kural Dışı Durum Sınıfı Tanımlama Bir try Bloğuyla Çok Sayıda catch Kullanımı İç İçe try - catch Blokları finally Bloğu
Konular Kural Dışı Durumlar try ve catch Blokları ve throw Komutu Kural Dışı Durum Sınıfı Tanımlama Bir try Bloğuyla Çok Sayıda catch Kullanımı İç İçe try - catch Blokları finally Bloğu
İç İçe try - catch Blokları İç içe if-else ifadeleri kullanıldığı gibi iç içe try-catch blokları da kullanılabilir. try try... cath ()... cath ()...
Konular Kural Dışı Durumlar try ve catch Blokları ve throw Komutu Kural Dışı Durum Sınıfı Tanımlama Bir try Bloğuyla Çok Sayıda catch Kullanımı İç İçe try - catch Blokları finally Bloğu
finally Bloğu try-catch bloklarının sonuna finally bloğu yazılabilir. finally bloğu içindeki kod, try bloğu içinde kural dışı durum olsa da olmasa da çalışır. try-catch-finally üçlüsünün çalışması sırasında 3 durum ortaya çıkabilir: Programda hiçbir kural dışı durum oluşmaz ve catch bloğu çalışmaz. finally bloğu çalışır. Programda kural dışı bir durum oluşur ve catch bloğu tarafından yakalanır. Try bloğu özel durum oluşan noktada kesilir ve catch bloğu ardından da finally bloğu çalışır. Try bloğunda bir kural dışı durum oluşur ancak catch bloğunda uygun bir parametre olmadığından yakalanamaz. Ancak yine finally bloğu çalıştırılır.
finally Bloğu finally bloğu içerisindeki kod mutlaka çalışması gereken koddur. Neden böyle bir şeye gerek duyulur? istisna oluşması programın akışına yön değiştirten bir durumdur. Bazı metotların işlemesi mutlak gerekli ise bu durum ciddi problemler yaratabilir. Bu tip problemlerin oluşmaması için finally bloğu kullanılır. Örneğin açık kalmış dosyaların kapatılması gibi işlemler genelde finally bloğu içerisine yazılarak olası problemler engellenmiş olur.
finally Bloğu Scanner klavye = new Scanner(System.in); try System.out.print( Bolunecek sayi:\t ); int a = klavye.nextint(); System.out.print( Bolen sayi:\t ); int b = klavye.nextint(); if (b == a) throw new Exception( Bolen Sifir! ); int c = a / b; System.out.println(a + / + b + = + c); cath () System.out.println(ozelDurum.getMessage()); System.out.println( Bolen Sifir Olamaz! ); finally System.out.println( Bu ileti her durumda basilir! );
Dikkat System.exit(); Eğer System sınıfının statik bir yordamı olan exit() çağrılırsa finally bloğuna hiç girilmez. System.exit() yordamı uygulamanın içerisinde çalıştığı JVM'i (Java virtual machine) kapatır. exit() yordamına gönderilen eksi bir değer JVM'in anormal bir sonlanış yapacağını ifade eder.
ÖZET İstisnalar için izlenen kod, bir try bloğu içerisinde tutulur. Bu bloğun anlamı bu kodu çalıştır ve istisna oluşacak mı gör Eğer try bloğu içerisinde bir istisna meydana gelirse, bir istisna nesnesi yaratılır ve kod içerisine atılır. Program bu istisnayı catch ifadesi ile yakalayabilir ve işleyebilir. Her catch bloğu ne tipte bir istisnayı yakalayabileceğini belirler ve içerisinde o tipte istisnayı işlemek üzere bir istisna işleyici bulunur. Eğer programcı bir istisnayı bizzat atmak istiyorsa throw ifadesini kullanır. Bir metottan atılan her istisna bir throws kalıbı ile belirtilir. finally ile belirtilen bloğun içindeki kod, istisna oluşsun veya oluşmasın kesinlikle çalışması gereken koddur. Bazı kodların her ne olursa olsun çalışması gerekiyorsa finally bloğunun içinde yer almalıdır.