Java Programlama İstisnalar, Numaralandırmalar, Otomatik Kutulama ve Açıklama Notları İstisnalar (Exceptions) • Programlar beklenmedik durumlar ortaya çıkarabilir • Bu beklenmedik durumlar, önceden, hata kodlarına dayalı olarak yönetilmekteydi (örn: C ve Linux) • Yeni programlama dillerinde hata yönetim mekanizmaları (exception handling machanism) kullanılmaktadır • Hata yönetim mekanizmaları daha güçlü ve esnek bir şekilde beklenmedik durumların yönetimini sağlarlar İstisna Hiyerarşisi Java’da istisnalar Throwable sınıfından türetilir ve aşağıdaki hiyerarşiye sahiptir. İstisna Ortaya Çıkarma ve Yakalama • İstisnalar, hatalı durumların yakalanmasını ve kontrol edilmesini sağlarlar • java.lang.Exception sınıfından türetilirler • Hatayla karşılaşan kod istisna fırlatır (throw an exception) • Hatanın kontrol edilmesini sağlayan kod istisnayı yakalar (catch the exception) Yakalanmamış İstisna Örneği - main metotu class Exc0 { public static void main(String args[]) { int d = 0; int a = 42 / d; System.out.println("Deneme"); } } Java çalışma ortamı, sıfıra bölme girişimine rastladığı zaman, yeni bir istisna nesnesi oluşturur ve bu istisnayı fırlatır İstisna Yaşam Döngüsü • Bir istisna fırlatıldığında, bu istisna bir istisna yöneticisi tarafından yakalanarak yönetilmelidir • İstisna yakalanana kadar metot çağırım yığınında (method call stack) yukarı doğru ilerler • Bir önceki slayttaki örnekte kendi istisna yöneticimizi yazmadık • İstisna Java çalışma ortamı tarafından sağlanan varsayılan istisna yöneticisi tarafından yakalanmış • Hatanın başladığı yerden itibaren yığını izini ekrana yazdırılmış ve • Program akışı yarıda kesilmiştir İstisna Yakalama Kendi istisna yöneticimizi yazarak aşağıdaki şekilde istisnayı yakalayabiliriz: try { // İstisna üretebilecek birşeyler yap } catch (Exception e) { } // Hata mesajini String değişkenine ata String errorMsg = e.getMessage(); // ... Yakalanmış İstisna Örneği public static void main(String args[]) { int d, a; try { // monitor a block of code. d = 0; a = 42 / d; System.out.println("This will not be printed."); } catch (ArithmeticException e) { // catch divide-by-zero error System.out.println("Division by zero."); } System.out.println("After catch statement."); } Sınıf Metotlarındaki İstisnalar • Metotlar bir istisna ortaya çıkarabileceklerini throws ifadesi ile belirtirler • Bu metotları çağıran metotlar, ya bu istisnayı yakalamalıdır ya da throws ifadesini kullanmalıdır • Örnek: void method() throws Exception { // ... } try { method(); } catch (Exception e) { // ... } Yakalanmamış İstisna Örneği - Sınıf Metotu class Exc1 { static void subroutine() { int d = 0; int a = 10 / d; } public static void main(String args[]) { Exc1.subroutine(); } } Yığın İzi (Stack Trace) • İstisna yakalanana kadar metot çağırım yığınında (method call stack) yukarı doğru ilerler • Sorunu anlamak için, istisnanın yığın izini printStackTrace() metodunu kullanarak ekrana yazabilirsiniz • Bir sonraki slayttaki kodu çalıştırarak, ekrana yazılan yığın izine dikkat edin Yığın İzi Örneği public static void main(String args[]) { int d, a; try { // monitor a block of code. d = 0; a = 42 / d; System.out.println("This will not be printed."); } catch (ArithmeticException e) { // catch divide-by-zero error e.printStackTrace(); } System.out.println("After catch statement."); } Throw ile İstisna Fırlatma • throw anahtar kelimesi ile kendimiz istisna fırlatabilirsiniz • Büyük bir yazılım projesinde kendi istisnalarımızı oluşturup, gerektiğinde bu istisnaları ortaya çıkarmalı ve yakalamalıyız • İstisna ortaya çıkaran kod örneği: boolean error; if (error) throw new Exception("Error condition"); Uygulama Önceki örnekteki yakalanmamış istisna kodundaki istisnayı, fırlatıp ve yakalayarak (throws ve catch ekleyerek) ekrana bir hata mesajı yazdırınız. Farklı İstisna Tiplerinin Yakalanması • Exception alt sınıfları tanımlanabilir • throws ifadesi birden fazla istisna tipini belirtebilir • Birden fazla catch ifadesi kullanılarak farklı istisna tiplerinin farklı şekillerde kontrol edilmesi sağlanabilir • İstisna sadece ilk uyumlu catch ifadesi tarafından kontrol edilir • Örnek: try { // ... } catch (ExceptionSubClass e) { // ... } catch (Exception e) { // ... } Finally Bloğu • İstisna oluşması durumunda dahi çalışması istenilen kod parçacıkları finally bloğu içerisine yazılır • Örnek: try { // ... } catch (Exception e) { // ... } finally { // try-catch bloğundan sonra çalıştırılır } Denetlenmeyen İstisnalar (Unchecked Exceptions) (1/2) • Normal istisnalar denetlenen istisnalardır (checked exceptions) • Metotlar try-catch bloğuna sahip olmalı yada throws idadesini kullanmalıdır • Derlenme zamanında bu kural kontrol edilir • Denetlenen istisnalar gereksiz kod yazımına neden olabilir • Bir istisna hiç bir zaman gerçekleşmeyecek olsa bile, kontrol edilmelidir (yakalanmalıdır) • Denetlenmeyen istisnaların kontrol edilmesi zorunlu değildir • Ancak eğer gerekli ise kontrol edilebilir • java.lang.RuntimeException ve bu sınıfın alt sınıfları denetlenmeyen istisnalardır Denetlenmeyen İstisnalar (Unchecked Exceptions) (2/2) • RuntimeException sınıfının java.lang paketinde bulunan ve sık karşılaşılan alt sınıfları: • ClassCastException eğer temel sınıftan alt sınıfa dinamik çevrim gerşekleştirilemezse • IllegalArgumentException eğer bir metota, kabul edilemeyecek bir parametre gönderilirse • IndexOutOfBoundsException eğer varolmayan bir dizi elemanına erişilmeye çalışılmışsa • NullPointerException eğer nesne referansı hafızada yer almayan bir nesneyi gösteriyorsa ve nesnenin üyesine erişilmeye çalışılırsa (nesne değişkeni: null) Kendi İstisnalarınızın Oluşturulması • Java’nın kendi istisnaları pek çok yaygın hatayı yönetebilmenizi sağlar • Ancaki kendi uygulamalarınıza özgü durumları veya hataları yönetmek için kendi istisnalarınızı oluşturmak isteyebilirsiniz • Kendi istisnanızı oluşturmak için Exception sınıfından bir alt sınıf oluşturmalısınız • Kendi istisnanız için en azından bir yapıcı tanımlamanız ve toString() metodunun üzerine yazmanız uygun olacaktır Yeni İstisna Sınıfı: MyException class MyException extends Exception { private int detail; MyException(int a) { detail = a; } public String toString() { return "MyException[" + detail + "]"; } } Yeni İstisna Sınıfının Kullanımı (1/2) static void compute(int a) throws MyException { System.out.println("Called compute(" + a + ")"); if (a > 10) throw new MyException(a); System.out.println("Normal exit"); } Yeni İstisna Sınıfının Kullanımı (2/2) public static void main(String args[]) { try { compute(1); compute(20); } catch (MyException e) { System.out.println("Caught " + e); } } Zincirleme İstisnalar (Chained Exceptions) • JDK 4 ile birlikte gelmiş bir özelliktir • Bir istisna ile başka bir istisnayı ilişkilendirmeyi sağlar • İkinci istisna birinci istisnanın nedenini tanımlar • Zincirleme istisnaların kullanımı için Throwable sınıfına iki yeni yapıcı ve iki yeni metot eklenmiştir Throwable(Throwable istisnaNedeni) Throwable(String mesaj, Throwable istisnaNedeni) Throwable getCause() Throwable initCause(Throwable istisnaNedeni) Zincirleme İstisna Örneği (1/2) static void demoproc() { // create an exception NullPointerException e = new NullPointerException("top layer"); // add a cause e.initCause(new ArithmeticException("cause")); throw e; } Zincirleme İstisna Örneği (2/2) public static void main(String args[]) { try { demoproc(); } catch (NullPointerException e) { // display top level exception System.out.println("Caught: " + e); // display cause exception System.out.println("Original cause: " + e.getCause()); } JDK 7 ve İstisnalar • JDK 7 ile birlikte istisnalarla ilgili üç yeni özellik gelimiştir • Kaynaklarla birlikte try (try-with-resources) • Çoklu yakalama • Daha net yeniden fırlatma (final rethrow) • Kaynalarla birlikte try, bir kaynağın (örneğin dosyanın) onunla işimiz bittikten sonra otomatik olarak kapatılmasını sağlar. Dosyalar konusunda anlatılacaktır • Çoklu yakalama, aynı catch bloğu ile birden fazla istisna tipinin yakalanmasını sağlar • Daha net yeniden fırlatma JDK 7 ve İstisnalar • JDK 7 ile birlikte istisnalarla ilgili üç yeni özellik gelimiştir • Kaynaklarla birlikte try (try-with-resources) • Çoklu yakalama • Kaynalarla birlikte try, bir kaynağın (örneğin dosyanın) onunla işimiz bittikten sonra otomatik olarak kapatılmasını sağlar. Dosyalar konusunda anlatılacaktır • Çoklu yakalama, aynı catch bloğu ile birden fazla istisna tipinin yakalanmasını sağlar • Bir sonraki slaytta çoklu yakalama örneği gösterilmektedir Çoklu İstisna Yakalama Örneği public static void main(String args[]) { int a = 10, b = 0; int vals[] = { 1, 2, 3 }; try { int result = a / b; // generate an ArithmeticException // vals[10] = 19; // generate an ArrayIndexOutOfBoundsException // This catch clause catches both exceptions. } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) { System.out.println("Exception caught: " + e); } System.out.println("After multi-catch."); } Numaralandırmalar (Enumerations) • Numaralandırma, adlandırılmış sabitlerden oluşan bir listedir • Numaralandırmalar, kavramsal olarak basit olsalar da pek çok diğer dilde bulunan bu özellik, pek çok programda kullanılabilir • JDK 5’ten itibaren Java’ya eklenmiştir • Java’da bir numaralandırma bir sınıf tipi tanımlar • Bu diğer dillerdeki numaralandırma yapılarına göre esneklik sağlar • Örneğin C++’da numaralandırmalar, sadece adlandırılmış tamsayı sabitlerdir Numaralandırmaların Tanımlanması (1/2) • Numaralandırma, enum anahtar sözcüğü kullanılarak oluşturulur • Aşağıda değişik elma türlerini listeleyen basit bir numaralndırma tanımlanmıştır: enum Apple { Jonathan, GoldenDel, RedDel, Winesap, Cortland } Numaralandırmaların Tanımlanması (2/2) enum Apple { Jonathan, GoldenDel, RedDel, Winesap, Cortland } • Jonathan, GoldenDel gibi tanımlayıcılar, numaralandırma sabitleri olarak adlandırılır • Her biri Apple sınıfının, public, static ve final birer üyesidir • Her birinin tipi ise tanımlandıkları numaralandırmanın tipidir: Apple Numaralandırma Kullanımı • Numaralandırmalar bir sınıf tipi tanımlasa da, new anahtar kelimesi kullanarak bir enum örneği oluşturamazsınız • Aksine, bir numaralandırma değişkenini, tıpkı temel veri tiplerini tanımlayıp kullandığınız gibi kullanmalısınız Apple ap; ap = Apple.RedDel; if (ap == Apple.RedDel) //… Numaralandırma Kullanım Örneği (1/2) public static void main(String args[]) { Apple ap; ap = Apple.RedDel; // Output an enum value. System.out.println("Value of ap: " + ap); System.out.println(); ap = Apple.GoldenDel; // Compare two enum values. if (ap == Apple.GoldenDel) System.out.println("ap contains GoldenDel.\n"); Numaralandırma Kullanım Örneği (2/2) switch (ap) { case case case case case } } Jonathan: System.out.println("Jonathan is red."); break; GoldenDel: System.out.println("Golden Delicious is yellow."); break; RedDel: System.out.println("Red Delicious is red."); break; Winesap: System.out.println("Winesap is red."); break; Cortland: System.out.println("Cortland is red."); break; values() ve valueOf() Metotları • Tüm numaralandırmalar otomatik olarak, önceden tanımlı iki metot içerir: values() ve valueOf() public static enum-tipi[] values() public static enum-tipi valueOf(String param) • values() metotu, numaralandırma sabitlerinin listesini içeren bir dizi döndürür • valueOf() metotu kendisine göderilen karakter katarına karşılık gelen numaralandırma sabitini döndürür values() ve valueOf() Metotları Örneği public static void main(String args[]) { Apple ap; System.out.println("Here are all Apple constants"); // use values() Apple allapples[] = Apple.values(); for (Apple a : allapples) System.out.println(a); System.out.println(); // use valueOf() ap = Apple.valueOf("Winesap"); System.out.println("ap contains " + ap); } Numaralandırma Sınıf Tipleri • Java numaralandırması bir sınıf tipidir • Her ne kadar new kullanarak yeni bir örnek oluşturulamazsa da, bunun dışında diğer sınıflarla aynı yeteneklere sahiptir • Örneğin bir numaralandırma tipine aşağıdaki özellikler eklenebilir: • Yapılandırıcılar • Değişkenler • Metotlar • Hatta numaralandırma tipipyle bir arayüzü gerçekleştirebilirsiniz Genişletilmiş Apple Numaralandırması enum Apple { Jonathan(10), GoldenDel(9), RedDel(12), Winesap(15), Cortland(8); private int price; // price of each apple // Constructor Apple(int p) { price = p; } int getPrice() { return price; } } Genişletilmiş Apple Numaralandırması Kullanımı public static void main(String args[]) { Apple ap; // Display price of Winesap. System.out.println("Winesap costs " + Apple.Winesap.getPrice() + " cents.\n"); // Display all apples and prices. System.out.println("All apple prices:"); for (Apple a : Apple.values()) System.out.println(a + " costs " + a.getPrice() + " cents."); } Numaralandırmalar Enum Sınıfını Temel Alır • Numaralandırmalar java.lang.Enum sınıfını temel alır • Bu sınıftan devralınan metotlar: • final int ordinal() • final int compareTo(enum-tipi e) • Final int equals(enum-tipi e) • ordinal(), numaralandırma sabitinin, sabitler listesindeki konumunu döndürür • compareTo(), iki sabitin ordinal değerlerini karşılaştırır • equals(), bir numaralndırma sabitini diğer herhangi bir nesneyle eşitlik bakımından karşılaştırabilirsiniz java.lang.Enum Metotları Örneği (1/2) public static void main(String args[]) { Apple ap, ap2, ap3; // Obtain all ordinal values using ordinal(). System.out.println("Here are all apple constants and their ordinal values: "); for (Apple a : Apple.values()) System.out.println(a + " " + a.ordinal()); ap = Apple.RedDel; ap2 = Apple.GoldenDel; ap3 = Apple.RedDel; System.out.println(); java.lang.Enum Metotları Örneği (2/2) if (ap.compareTo(ap2) < 0) System.out.println(ap + " comes before " + ap2); if (ap.compareTo(ap2) > 0) System.out.println(ap2 + " comes before " + ap); if (ap.compareTo(ap3) == 0) System.out.println(ap + " equals " + ap3); System.out.println(); if (ap.equals(ap2)) System.out.println("Error!"); if (ap.equals(ap3)) System.out.println(ap + " equals " + ap3); if (ap == ap3) System.out.println(ap + " == " + ap3); } Tip Uyumlulaştırıcıları (1/2) • Java dilindeki temel veri tipleri: int, double gibi • Bu tipler için nesnelerin kullanılması performans açısından bir dezavantaja neden olur • Bu nedenle temel veri tipleri nesne hiyerarşisi içerisinde yer almazlar • Object sınıfından türetilmemişlerdir • Temel tipler bir performans avantajı sağlasa da, bu tipler için bir nesne temsiline ihtiyaç duyduğumuz durumlar olabilir • Örneğin, Java’da gerçekleştirimi olan pek çok veri yapısı nesneler üzerinde çalışır Tip Uyumlulaştırıcıları (2/2) • Bu durumlarla başa çıkabilmek için tip uyumlulaştırıcıları (type wrappers) kullanılır • Bunlar temel veri tipini bir nesne içinde sarmalayan sınıflardır • Tip uyumlulaştırıcıları: • Character • Boolean • Double, Float, Long, Integer, Short, Byte (sayısal tip uyumlulaştırıcılar) Character Tip Uyumlulaştırıcısı • Yapılandırıcı: Character(char c) • Bir Character nesnesinde tutulan char değerini elde etmek için: char charValue() Boolean Tip Uyumlulaştırıcısı • Yapılandırıcılar: Boolean(bool b) Boolean(String strBool) • Bir Boolean nesnesinde tutulan bool değerini elde etmek için: boolean booleanValue() Sayısal Tip Uyumlulaştırıcıları (1/2) • Tüm sayısal tip uyumlulaştırıcıları, herhangi bir değerden veya değerin karakter katarından yapılandırılabilmesini sağlayan yapıcılar içerir. • Örneğin Integer için tanımlanmış yapıcılar: Integer(int b) Integer(String strInt) • Örneğin Double için tanımlanmış yapıcılar: Double(double d) Double(String strDouble) Sayısal Tip Uyumlulaştırıcıları (2/2) • Sayısal tip uyumlulaştırıcılarının hepsi Number sınıfından türetilmiştir. • Number sınıfında, sayının farklı tiplerde değerlerini döndürebilen aşağıdaki metotlar tanımlanmıştır: byte byteValue() double doubleValue() float floatValue() int intValue() long longValue() short shortValue() Sayısal Tip Uyumlulaştırıcısı Örneği class Wrap { public static void main(String args[]) { Integer iOb = new Integer(100); int i = iOb.intValue(); System.out.println(i + " " + iOb); // displays 100 100 } } Otomatik Kutulama • JDK 5’ten itibaren Java diline iki önemli özellik eklenmiştir: • Otomatik kutulama (autoboxing) • Otomatik kutudan çıkarma (auto-unboxing) • Otomatik kutulama, belirli bir tipte nesne gerektiğinde, bir temel tipin otomatik olarak karşılık gelen tip uyumlulaştırıcısına çevrilmesidir • Otomatik kutudan çıkarma ise, tersi işlemin otomatik olarak gerçekleşmesidir • Bu özellikler, pek çok algoritmanın kodlanmasını programcı açısından kolaylaştırmıştır • Hataların önlemeye yardımcı olur ve jenerikler için de çok önemlidir Otomatik Kutulama Örneği class AutoBox { public static void main(String args[]) { Integer iOb = 100; // autobox an int int i = iOb; // auto-unbox System.out.println(i + " " + iOb); // displays 100 100 } } Otomatik Kutulama ve Metotlar // Take an Integer parameter and return an int value; static int m(Integer v) { return v; // auto-unbox to int } public static void main(String args[]) { // Pass an int to m() and assign the return value // to an Integer. Here, the argument 100 is autoboxed // into an Integer. The return value is also autoboxed // into an Integer. Integer iOb = m(100); System.out.println(iOb); } Deyimlerde Otomatik Kutulama ve Kutudan Çıkartma (1/2) class AutoBox3 { public static void main(String args[]) { Integer iOb, iOb2; int i; iOb = 100; System.out.println("Original value of iOb: " + iOb); // The following automatically unboxes iOb, // performs the increment, and then reboxes // the result back into iOb. ++iOb; System.out.println("After ++iOb: " + iOb); Deyimlerde Otomatik Kutulama ve Kutudan Çıkartma (2/2) // Here, iOb is unboxed, the expression is // evaluated, and the result is reboxed and // assigned to iOb2. iOb2 = iOb + (iOb / 3); System.out.println("iOb2 after expression: " + iOb2); // The same expression is evaluated, but the // result is not reboxed. i = iOb + (iOb / 3); System.out.println("i after expression: " + i); } } Açıklama Notları (Annotations) • Java kaynak kodları için üst veriler (metadata) • Tanımlamalara uygulanır • Sınıfların, değişkenlerin, metotların ve yerel değişkenlerin tanımlanmalarında üst veri bildirmek için kullanılır • @ karakteri ile başlar • Ön tanımlı açıklama tipleri: • @Deprecated • @Override • @SuppressWarnings • Warning types: deprecation, unused, null • Örnek: @SuppressWarnings("unused") Ön Tanımlı Açıklama Notları (1/2) • @Override • Sadece metotlar üzerinde kullanılabilen bir işsaretleyici nottur • Bir üst sınıftaki metotun üzerine yazıldığını belirtir • Eğer üst sınıfta böyle bir metot yoksa bir derleme zamanı hatası oluşur • @Deprecated • Bir tanımlamanın eski olduğunu ve aynı işlemin artık farklı bir şekilde gerçekleştirildiğini belirten işretleyici nottur • Örneğin, Java 4’te bulunan ama Java5’te bulunmayan bir metot, Java5’te @deprecated olarak işaretlenir Ön Tanımlı Açıklama Notları (2/2) • @SuppressWarnings • Derleyici tarafından verilebilecek bir ya da daha çok uyarının göz ardı edileceiğini belirtir • Bastırılacak uyarılar, karakter katarı formunda adlarıyla belirtilir • Örnek: @SuppressWarnings("unused") • Bastırılacak uyarı tiplerinden bazılarına karşılık gelen karakter katarları: • • • • all – tüm uyarılar unused – kullanılmayan yerel değişkenler veya özel metotlar için uyarılar deprecation – eskiden tanımlı metotların veya değişkenlerin kullanımı için uyarılar null – null analizi ile ilişkili uyarılar