6.1 Using the throw statement and the throws clause
6.1.1 Creating a method that throws a checked exception
6.1.2 Using a method that throws a checked exception
6.1.3 Creating and using a method that throws runtime exceptions or errors
6.1.4 Points to note while using the throw statement and the throws clause
6.2 Creating custom exceptions
6.2.1 Creating a custom checked exception
6.2.2 Creating a custom unchecked exception
6.3 Overriding methods that throw exceptions
6.4 Using the try statement with multi-catch and finally clauses
6.4.1 Comparing single-catch handlers and multi-catch handlers
6.4.2 Handling multiple exceptions in the same exception handler
6.5 Auto-closing resources with a try-with-resources statement
6.5.1 How to use a try-with-resources statement
6.6.1 Exploring the forms of assertions
6.6.2 Testing invariants in your code
6.6.3 Understanding appropriate and inappropriate uses of assertions
Bu chapterda Exceptions ve Assertions öğreneceğiz.
{width=”4.958333333333333in”
height=”1.6666666666666667in”}
{width=”6.3in”
height=”3.7604516622922133in”}
Metod imzasına throws yazarak veya bir üst metodda yakalayarak hata fırlatılabilir. “runtime exceptions” ve “errors” u metod imzasında tanımlamaya gerek yoktur. Bir metod bunlar tanımlanmasa bile bu hata tiplerini fırlatabilir.
Bir Checked Exception’ı ya yakalamalı ya da metod imzasında tanımlamalıyız. Bu kurala “handle-or-declare” kuralı denir. Bu kural “unchecked exception” larda geçerli değildir.
Bir metodda bu kuralın her ikiside tanımlanabilir. Metod kesinlikle hata fırlatmıyor olsa bile handle etmemiz şarttır.
Runtime Exception’ları ve error ları yakalamak zorunda değiliz. Method imzasına da yazabiliriz ama hiçbir etkisi olmamaktadır. Unchecked Exceptionlar tanımlansada tanımlanmasada metod tarafından fırlatılabilir. Aşağıdaki liste genel Unchecked Exceptionları göstermektedir.
{width=”5.25in” height=”2.2291666666666665in”}
public void readFile(String file) throws FileNotFoundException {
throw new IOException("Missing file"); // BU SATIR DERLENMEZ!!
}
public void readFile(String file) throws IOException {
throw new FileNotFoundException("Missing file"); // BU SATIR DERLENİR!!!
}
Bu kural error ve runtime Exception’larda geçerli değildir.
void useReadFile(String name) throws FileNotFoundException {
throw new FileNotFoundException("Missing file");
}
public static void main(String args[]) throws IOException, SQLException {
public static void main(String args[]) throws IOException, SQLException {
try {
if (source.equals("DBMS"))
throw new SQLException();
else
throw new IOException();
}
catch (Exception e) {
throw e; // Bu satır hata vermez. JVM içindekinin tipini bilir…
throw new Exception(); // Bu satır hata verirdi!
}
void method9() {
try {}
catch (RuntimeException e) {} // Bu metod derlenir!
}
void method10() {
try {}
catch (FileNotFoundException e) {} // Bu Method Derlenmez!
}
FileNotFoundException extends IOException extends Exception
{width=”6.3in” height=”3.839876421697288in”}
Checked Exception’ımızı kendimiz tanımlamak için java.lang.Exception sınıfı ve alt sınıflarından extend etmeliyiz.(Runtime hariç) Burada throwable dan da extend edebiliriz ama tavsiye edilmez. Çünkü OutOfMemoryError da dahil her hatayı yakalamış oluruz bu şekilde.
Aynı şekilde java.lang.RuntimeException sınıfından extend ederek RunTimeException, java.lang.Error dan extend ederek de Error oluşturabiliriz. Ama error oluşturma tavsiye edilmez.
{width=”5.1875in” height=”3.4652777777777777in”}
Bu kurallar tabiiki sadece Checked Exception’lara uygulanır.
class Base {
public void aMethod() {}
public void noRuntimeException() {}
}
class Derived extends Base {
public void aMethod() throws Exception {} // DERLENMEZ!
public void noRuntimeException() throws RuntimeException {} // DERLENİR!
}
class Base {
public void aMethod() throws IOException {}
public void withRuntimeException() throws RuntimeException {}
}
class Derived1 extends Base {
public void aMethod() {}
public void withRuntimeException() {}
}
class Base {
public void aMethod() throws IOException {}
public void withRuntimeException() throws NullPointerException {}
}
class Derived2 extends Base {
public void aMethod() throws Exception {} // BU SATIR DERLENMEZ!
public void withRuntimeException() throws RuntimeException{}
}
class Base {
void aMethod() throws IOException {}
void methodUncheckedEx() throws Error {}
}
class Derived3 extends Base {
void aMethod() throws IOException {}
void methodUncheckedEx() throws NullPointerException {}
}
class Base {
void aMethod() throws IOException {}
}
class Derived4 extends Base {
void aMethod() throws FileNotFoundException {}
}
Java 7 ile birlikte catch içinde birden fazla hata yakalanmasına izin verilmiştir.
catch (IOException | SQLException ex)
Tek satırda birbiri ile alakasız Exception sınıfları yakalanabilir;
catch (FileNotFoundException | MyCustomException | NumberFormatException e){
//process exception
}
Burada dikkat edilecek konu yukardaki satırda 3 adet exception yakalanır ve ayrıca bu exception’ların alt sınıfları da yakalanır.
Multi-catch bloklarında subClass’lar hiçbir şekilde yanyana yazılamaz, yazılırsa kod derlenemez.
catch (IOException | FileNotFoundException | SQLException e) // BU SATIR DERLENMEZ!
catch (FileNotFoundException | IOException | SQLException e) // BU SATIR DERLENMEZ!
catch (IOException | SQLException e) // DERLENİR!
Multi-catch ile single-catch kombine edilebilir.
catch (FileNotFoundException e) {}
catch (IOException | SQLException e) {} //FileNotFoundException ve altını yakalar.
Multi-catch bloğunda e sadece bir tane olabilir. Bu e değişkeni Final dır. Tekrar atama yapılmaz. Aşağıdaki satır derlenmez.
catch (IOException| SQLException e) {
e = new FileNotFoundException();
}
Multi-catch bloğunda e değişkenin referance variable’ı “Exception” dır! Yukarıdaki örnekte e değişkeni IO veya SQL exception değil, Exception dır. Bunun sadece bir istisnası vardır. intersection type özelliği ile Exception sınıfının metodlarına ulaşabiliriz. Örnek kod chapter6.s4 içinde var.
**Exception sınıfları toString() metodu sınıf ismini ve hata mesajını yazdırırlar! **
( Exception toString() == java.io.FileNotFoundException: Hata mesajı(varsa) )
Java 7 ile gelen try-with-resources özelliği içindeki kaynakları otomatik olarak kapatmaktadır.
Bu try blokları java.lang.AutoCloseable interface’ini implemente eden sınıfları try’ın son satırında ilgili nesnenin close() metodunu çağırarak otomatikman kapatır. Try içinde tanımlanması şu şekildedir;
try (FileInputStream fin = new FileInputStream(file)){
}catch (IOException e) {
System.out.println(e.toString());
}
// veya
try (FileInputStream fin = new FileInputStream(file);){
Try içindeki satır FileNotFoundException hatası fırlatabilir. Ama catch içinde sadece FileNotFoundException tanımlar isek çalışmaz! Sebebi ise try’ın otomatik olarak close() metodunu çağırması ve close metodunun da hata olduğu zaman IOException fırlatmasıdır. Her ikisini sağlayacak yukardaki gibi bir catch yazar isek sorun yaşanmayacaktır.
try-with-resources özelliğinde try içinde(initalizion kısmı hariç) bir hata fırlatılıyor ve o sırada try’in son metodu olan close() ‘da da hata alınıyor ise; try içinde hata alındıktan sonra close metodu içi çağrılır. Burada da hata alınıyor ise bu hatalar supress edilir ve try içindeki hata fırlatılır. Bunun örneği chapter6.s5 içinde var.
Bu suppress edilen hatalara ise fırlatılan Exception içinde getSuppressed() metodundan ulaşabiliriz. Bu metod bize Throwable nesne dizisi döndürür. Aynıca bu metod asla null döndürmez. İçi boş ise size’ı 0 dır.
try-with-resources özellikleri;
{width=”5.3125in” height=”1.7708333333333333in”}
Uygulamalarımızı test ve debug etmek için bazen varsayımları düşünürüz. Bu varsayımları javada uygulamak için assertions ları kullanırız. Assert fonksiyonu bu iş için kullanılır. Bu fonksiyon true veya false döner. Biz varsayımımızın her zaman doğru olmasını isteriz. Ama gerçekleşmez ise burada AssertionError fırlatılır. Assertions lar disable edilmiştir, bü yüzden performans kaybına yol açmazlar. Açmak için Eclipse’de VM Arguments kısmına “-ea” parametresi yazılır.
Assertion tanımlamak için iki yöntem vardır, kısa ve uzun. Kısa yöntem;
assert expression; ( assert false; )
Uzun yöntem ise ;
assert expression : Ezpression ; ( assert false : "Testing Assertions"; )
şeklindedir. Her iki yöntemde expression false olursa AssertionError fırlatılır. Her iki expression’ının da boolean dönmesi gerekir. Fakat uzun yöntemdeki Expression herhangi bir primitive veya nesne dönebilir. Ama dönmek zorundadır. Yoksa derlenmez! Nesne döndüğü durumlarda ise ilgili nesnenin toString() metodu çağrılarak sonucu yazdırılır.
Değişmezleri kodda test etmek için 3’e ayıralım.
Assertions’lar bir sınıf ve bir package için ayrıca kapatılabilir;
java --ea DemoAssertion
java --enableassertions DemoAssertion
java --da DemoAssertion
java --disableassertions DemoAssertion