Exception Handling

เมื่อกล่าวถึงข้อผิดพลาดของโปรแกรมตอน runtime อาจเกิดขึ้นได้เสมอเช่น memory
ถูกใช้ไปหมด การอ้างถึงตำแหน่งใน array ที่ไม่มีอยู่จริง การอ้างถึง member ใน reference ที่ไม่ได้ถือ instance ใดๆไว้เลย ภาษา Java รองรับการดักจับข้อผิดพลาด
เหล่านี้ เพื่อให้โปรแกรมสามารถทำงานต่อไปได้ หรือ ถ้าร้ายแรงอย่างน้อยก่อนที่
ระบบจะปิดลงก็ควรจะบันทึกข้อมูล log บางอย่างเป็นต้น

ข้อมูลความผิดพลาดต่างๆจะถูกโยนออกมาซึ่งเรียกว่า Exception ซึ่งจะมีอยู่
สองประเภทคือ

  • Checked Exception Compiler จะบังคับให้เราเตรียมรองรับเลยใน code เพราะเรา
    สามารถคาดเดาได้ล่วงหน้า
  • UnChecked Exception ส่วนใหญ่จะเป็น Error ที่ร้ายแรงและคาดเดาได้ยากว่า
    จะเกิดขึ้นเมื่อไหร่ Compiler ไม่บังคับให้ดักจับ exception กลุ่มนี้อันได้แก่
    RuntimeException และ Error ซึ่งหากเกิดขึ้นมาแล้ว jvm จะจบการทำงานทันที
    เพราะฉะนั้นเราจึงควรคาดเดาล่วงหน้าแล้วรองรับ exception เหล่านี้ด้วย

ลองดูตัวอย่างของ Exception ดูครับ

public class Test {

    public static void main(String[] args) {
        int i=1/0;
    }

}

ผลลัพท์ที่ได้จากการ run program คือ

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:4)

ArithmeticException เป็น Runtime Exception ซึ่งเป็น Unchecked Exception
นอกจากนี้ jvm ยังแสดงเลขที่บรรทัดบน source code ให้อีกด้วยว่าผิดพลาดตรงไหน

super class ของทุก Exception คือ Throwable กรณีที่เราคาดเดาความผิดพลาดได้
ล่วงหน้า เราสามารถใช้ keyword ดังนี้

       throw new Throwable();

ซึ่งเป็น Checked Exception เพราะฉะนั้นเราจึงต้องดักจับข้อผิดพลาดนี้ซึ่งทำได้สองวิธี
เช่น

//ใช้ try-catch block มาครอบ

    try {

           throw new Throwable();

    } catch (Throwable t) {
           t.printStackTrace();//แสดงข้อมูลของ error

    }

//propogation โดยโยนออกไปยังผู้ที่เรียก method นี้

    void test() throws Throwable {

           throw new Throwable();

   }

การ Propogation คือการโยน exception ออกไปเป็นทอดๆ โดยการเรียก method ที่มี
throws clause จะต้องดักจับ exception เช่นกัน คล้ายกับตัวอย่างข้างบนคือ

//ใช้ try-catch block มาครอบ

try {

          test();

} catch (Throwable t) {
          t.printStackTrace();

}

//propogation ออกไปอีก

 void call() throws Throwable {

         test();

}

แม้แต่ main method ก็ยังสามารถวาง throws clause ได้เช่นเดียวกัน โดยถ้า
มี Exception ออกมายังระดับนี้แล้วล่ะก็ jvm จะแสดงข้อมูล Exception ออกมา
แล้วสิ้นสุดการทำงาน

public static void main(String[]args) throws Throwable {

         call();

}

try-catch block และ throws clause สามารถรองรับ Exception ได้หลายประเภท
โดยที่ java.lang.Throwable จะมี sub class สองตัวคือ java.lang.Exception และ
java.lang.Error ซึ่งเป็น Unchecked Exception

ส่วน java.lang.RuntimeException เป็น sub class ของ java.lang.Exception
ซึ่งเป็น UnChecked และมี sub class มากมายซึ่งที่พบได้บ่อยๆเช่น

  • ArithmeticException เช่นการหารด้วย 0
     
  • ClassCastException เช่นการ Casting ผิดประเภท
     
  • IndexOutOfBoundsException เช่นการอ้างถึงตำแหน่งใน Array ที่ไม่มีอยู่จริง
     
  • NullPointerException เช่นการอ้างถึง member ใน reference ที่ไม่ได้ถือ
    instance ใดๆ

ตัวอย่าง

try {

     //..//

} catch(NullPointerException e) {

} catch(ArithmeticException e) {

} catch(Exception e) {

}

ซึ่งลำดับของการวาง catch ต้องเริ่ม sub class ไปหา super class
จากตัวอย่างข้างบนหากเกิด ClassException ซึ่งเราไม่ได้รองรับไว้
จะกระโดดมาเข้าีที่ catch (Exception e) หลักการเดียวกันกับ
overloading method

ส่วนการใช้ throws clause ก็ทำได้โดยใช้ , ขั้น Exception
ที่มีโอกาสเกิดขึ้นต่างๆเช่น

void test()throws NullPointerException, ArithmeticException, Exception {

      //..//

}

นอกจากนี้ยังสามารถใช้ try-catch block ร่วมกับ throws clause ได้ด้วยเช่น

void test()throws NullPointerException, ArithmeticException, Exception {

     try {

        //..//

    } catch(NullPointerException e) {

           throw e;

    } catch(ArithmeticException e) {

           throw e;

    } catch(Exception e) {

           throw e;

 

    }

}

สังเกตุว่า เราไม่จำเป็นต้อง new Exception ขึ้นมาใหม่ แต่สามารถ throw e
ออกไปได้เลย

Finally block

เนื่องจากเมื่อ throw Exception แล้ว statement หลังจากนั้นจะไม่ถูกทำเลย
แต่เราสามารถใช้ finally block เพื่อให้กระโดดมาทำหลังจากเกิด Exception แล้วได้

try {

        int i=1/0;
        System.out.println("Hello");//จะไม่ถูกทำ

} catch (Exception e) {

    System.out.println(e.getMessage());

} finally {

    System.out.println("Finally and Goodbye");

}

ผลลัพท์จากการ run program จะเป็นดังนี้

/ by zero
Finally and Goodbye

สอนพื้นฐาน Java
Line: wizarud
Gmail: [email protected]