การจัดการกับข้อผิดพลาด (Exception Handling) ในภาษาjava

โปรแกรมภาษาจาวาแบ่งข้อผิดพลาดที่อาจเกิดขึ้นขณะรันโปรแกรมเป็นสอง ประเภทคือ
Error เป็นข้อผิดพลาดที่ไม่สามารถแก้ไขและจัดการได้ เช่น  VirtualMachineError,OutOfMemoryError
Exception เป็นข้อผิดพลาดที่สามารถแก้ไขหรือจัดการได้ เช่น       ArrayIndexOutOfBoundsException, FileNotFoundException
ข้อผิดพลาดในภาษาจาวาจะกำหนดเป็นออปเจ็คของคลาสต่างๆ โดยมีคลาส Throwable เป็นคลาสราก
คลาสประเภท Exception
Exception เป็นข้อผิดพลาดที่เกิดในขณะรันโปรแกรมภาษาจาวา  Exception แบ่งออกเป็นสองประเภท คือ  RuntimeException และ IOException
RuntimeException เป็นข้อผิดพลาดที่อาจหลีกเลี่ยงได้หากมีการเขียนโปรแกรมที่ถูกต้อง
IOException เป็นข้อผิดพลาดที่ภาษาจาวากำหนดให้ต้องมีการจัดการ หากมีการเรียกใช้เมธอดที่อาจเกิดข้อผิดพลาดประเภทนี้ได้
คลาสประเภท Exception ที่สำคัญและพบบ่อย
ArithmeticException
ArrayIndexOutOfBoundsException
EOFException
FileNotFoundException
InterruptedException
IOException
NullPointerException
NumberFormatException
ตัวอย่างโปรแกรมที่อาจเกิดข้อผิดพลาด
public class ExceptionDemo {
  public static void main(String args[]) {
  System.out.println(args[2]);
  System.out.println("Hello");
  }
}
คำสั่ง try..catch
ภาษาจาวามีคีย์เวิร์ด try ที่เป็นคำสั่งที่ใช้ในการจัดการกับเมธอดหรือคำสั่งที่อาจเกิดข้อผิดพลาดซึ่งจะส่งออปเจ็คประเภท Exception ในขณะรันโปรแกรม
รูปแบบ
                                                try {
                                                [statements]
                                                }
โปรแกรมภาษาจาวาจะสั่งงานชุดคำสั่งที่อยู่ในบล็อกทีละคำสั่ง และหากเกิดข้อผิดพลาดขึ้นในคำสั่งประเภทใดก็จะมีการส่งออปเจ็คของข้อผิดพลาดประเภท Exception นั้นขึ้นมา
ในกรณีที่ต้องการจัดการกับข้อผิดพลาดที่เกิดขึ้น โปรแกรมจะต้องมีชุดคำสั่งอยู่ในบล็อกของคีย์เวิร์ด catch ที่จะระบุชนิดของออปเจ็คในคลาสประเภท Exception ที่ต้องการจัดการ
รูปแบบ
                                                catch(ExceptionType argumentName){
                                                [statements]
                                                }
ตัวอย่างโปรแกรมที่มีการจัดการกับข้อผิดพลาด
public class ExceptionHandlingDemo {
                public static void main(String args[]) {
                                try {
                                                System.out.println(args[2]);
                                } catch(ArrayIndexOutOfBoundsException ex) {
                                                System.out.println("There is no third command                                 line argument");
                                }
                }
}
การจัดการกับข้อผิดพลาดหลายๆประเภท
โปรแกรมภาษาจาวาสามารถจะมีชุดคำสั่งของบล็อก catch ได้มากกว่าหนึ่งชุดสำหรับในแต่ละบล็อกคำสั่ง try
ชนิดของออปเจ็คประเภท Exception ที่อยู่ในชุดคำสั่งของบล็อก catch  จะต้องเรียงตามลำดับการสืบทอด
ในกรณีที่มีข้อผิดพลาดเกิดขึ้น ภาษาจาวาจะพิจารณาว่าเป็นข้อผิดพลาดชนิดใด ซึ่งการที่จะจัดการกับออปเจ็คประเภท Exception นั้นจะพิจารณาจากคลาสที่มีการสืบทอดตามลำดับชั้น
ตัวอย่างโปรแกรม
public class ExceptionHandlingDemoV2 {
                public static void main(String args[]) {
                                try {
                                                int i = Integer.parseInt(args[0]);
                                                System.out.println(4 / i);
                                } catch(ArithmeticException ex) {
                                                System.out.println(ex.toString());
                                } catch(NumberFormatException ex) {
                                                System.out.println("Invalid numeric format");
                                }
                }
}
ตัวอย่างโปรแกรมที่ไม่ถูกต้อง
public class ExceptionHandlingDemoV3 {
                public static void main(String args[]) {
                                try {
                                                int i = Integer.parseInt(args[0]);
                                                System.out.println(4 / i);
                                                System.out.println(args[2]);
                                } catch(RuntimeException ex) {
                                                System.out.println(ex.toString());
                                } catch(ArrayIndexOutOfBoundsException ex) {
                                                System.out.println("There is no third command                                 line argument");
                                }
                }
}
บล็อก finally
ภาษาจาวามีคีย์เวิร์ด finally ที่จะมีชุดคำสั่งอยู่ในบล็อกเพื่อระบุให้โปรแกรมทำชุดคำสั่งดังกล่าวหลังจากสิ้นสุดการทำงานของชุดคำสั่งในบล็อก try หรือ catch
ภาษาจาวาจะทำชุดคำสั่งในบล็อก finally เสมอ แม้ว่าจะมีคำสั่ง return ในบล็อก try หรือ catch ก่อนก็ตาม กรณีเดียวที่จะไม่ทำชุดคำสั่งในบล็อก finally คือมีคำสั่ง System.exit();
ตัวอย่างโปรแกรม
public class FinallyDemo {
                public static void main(String args[]) {
                                try {
                                                System.out.println(args[2]);
                                                System.out.println("Hello");
                                } catch(ArrayIndexOutOfBoundsException ex) {
                                                System.out.println("There is no third argument");
                                } finally {
                                                System.out.println("Finish running the program");
                                }
                }
}
-----------------------------------------------------------------------------------------------------------------
public class FinallyDemoV2 {
   public static void main(String args[]) { 
  FinallyDemoV2 obj = new FinallyDemoV2();
  obj.myMethod(args);
   }
   public int myMethod(String args[]) {
  try {
  System.out.println(args[2]);
  return 0; 
  } catch(ArrayIndexOutOfBoundsException ex) {
  System.out.println("There is no third argument");
  } finally {
  System.out.println("Finish running the program");
  return 1;
  }
   }
}
การจัดการกับเมธอดที่ส่งออปเจ็คประเภท Exception
เราสามารถจะจัดการกับออปเจ็คของ Exception โดยใช้คลาสที่เป็น superclass ของ  Exception นั้นได้ อาทิเช่น เราสามารถจัดการกับ FileNotFoundException โดยใช้ IOException หรือ Exception แทนได้
การจัดการกับ Exception มีสองแบบ คือ
      1.ใช้คำสั่ง try/catch
      2.ใช้คำสั่ง throws ในการประกาศเมธอดที่จะมีการเรียกใช้เมธอดใดๆที่อาจส่งออปเจ็คประเภท Exception
คำสั่ง throws 
รูปแบบการใช้คำสั่ง throws มีดังนี้
                                [modifier] return_type methodName([arguments]) throws
                                                                                                ExceptionType[,ExceptionType2] {
                                                ...
                                }
ตัวอย่าง
                                public void openfile(String s) throws                                                                                                                       FileNotFoundException {
                                                ...
                                }
----------------------------------------------------------------------------------------------------------------------------------------
เมธอดใดๆสามารถที่จะจัดการกับ Exception โดยใช้คำสั่ง throws ได้มากกว่าหนึ่งประเภท
ตัวอย่าง
                                public void openFile(String s)throws                                                                       FileNotFoundException,UnknownHostException {
                                                                 ...
      }
กรณีที่มีการใช้คำสั่ง throws ส่งต่อไปเรื่อยๆ แล้วเมธอด main() ซึ่งเรียกใช้เมธอดสุดท้ายที่ใช้คำสั่ง throws ไม่มีการจัดการกับออปเจ็คประเภท Exception ดังกล่าว  โปรแกรมจะเกิดข้อผิดพลาดในขั้นตอนการรันโปรแกรม เมื่อมีข้อผิดพลาดของออปเจ็คประเภท Exception ดังกล่าวเกิดขึ้น
ตัวอย่างโปรแกรมที่ไม่มีการจัดการกับ Exception
public class ExceptionDemo1 {
                public static void main(String args[]) {
                                ExceptionDemo1 ex1 = new ExceptionDemo1();
                                ex1.method1();
                }
                public void method1() throws ArithmeticException {
                                method2();
                }
                public void method2() throws ArithmeticException {
                                System.out.println(2/0);
                }
 }
กฎของการกำหนดเมธอดแบบ overriden
เมธอดแบบ overriden จะไม่อนุญาตให้มีการจัดการออปเจ็คประเภท Exception โดยใช้คำสั่ง throws มากชนิดกว่าที่เมธอดเดิมจัดการอยู่ได้
ตัวอย่างโปรแกรมที่มีเมธอดแบบ overriden ที่ถูกต้อง
import java.io.*;
public class Parent {
                public void myMethods() throws IOException { }
}
public class OverrideException extends Parent{
                public void myMethods() throws IOException {
                                new FileInputStream("temp.txt");
                }
}
ตัวอย่างโปรแกรมที่มีเมธอดแบบ overriden ที่ไม่ถูกต้อง
import java.io.*;
public class Parent {
  public void myMethods() throws FileNotFoundException { }
}
public class OverrideExceptionV2 extends Parent {
                public void myMethods() throws                                                                              FileNotFoundException,IOException {
                                new FileInputStream("temp.txt");
                }
}
การสร้างคลาสประเภท Exception ขึ้นใหม่
การสร้างคลาสประเภท Exception ขึ้นมาใหม่ สามารถทำได้โดยนิยามคลาสใดๆให้สืบทอดมาจากคลาสที่ชื่อ Exception
โดยทั่วไปคลาสที่ชื่อ Exception จะมี constructor สองรูปแบบคือ public Exception()  และ public Exception(String s)
ดังนั้นคลาสที่สืบทอดมาจากคลาสที่ชื่อ Exception ควรจะมี constructor ทั้งสองแบบ โดยรูปแบบหนึ่งจะมี argument ที่มีชนิดข้อมูลเป็น String และมีคำสั่งแรกใน constructor เป็นคำสั่ง super(s);
ตัวอย่างคลาสประเภท Exception ที่กำหนดขึ้นใหม่
public class MyOwnException extends Exception {
                public MyOwnException (String s) {
                                super(s);
                }
}
การเขียนเมธอดเพื่อส่งออปเจ็คประเภท Exception
เมธอดที่ต้องการส่งออปเจ็คประเภท Exception  เมื่อเกิดข้อผิดพลาดขึ้นในคำสั่งใด จะต้องเรียกใช้คำสั่งที่ชื่อ  throw  เพื่อจะสร้างออปเจ็คของคลาสประเภท Exception ขึ้นมา
รูปแบบ                 throw new ExceptionType([arguments])
นอกจากนี้คำสั่งประกาศเมธอดนั้นจะต้องมีคำสั่ง throws เพื่อกำหนดให้คำสั่งในเมธอดอื่นๆที่เรียกใช้เมธอดนี้ต้องเขียนคำสั่งในการจัดการกับข้อผิดพลาดนี้
ตัวอย่างคลาส FileHandler
import java.io.*;
public class FileHandler {
    public static void openFile(String filename) throws                                                                            MyOwnException {
                 File f = new File(filename);
                 if (!f.exists()) {
                                throw new MyOwnException("File Not Found");
                 }
    }
}
ตัวอย่างโปรแกรมที่มีการจัดการกับข้อผิดพลาด
public class FileOpener {
                 public static void main (String args[]) {
                                try {
                                                FileHandler.openFile(args[0]);
                                                System.out.println("Open successful");
                                } catch (MyOwnException ex) {
                                                System.err.println(ex);
                                }
                 }
}