1. 程式人生 > >Java中異常的處理

Java中異常的處理

Java中的異常

分為Error和Exception,其中Error是指Java虛擬機器無法解決的嚴重問題,Exception是指外在因素導致的一般性問題,這裡我們討論的是Exception。

常見的Exception

有空指標異常、陣列下標越界異常、型別轉換異常、算術異常。

Exception的處理

抓拋模型:抓是指抓住上一步丟擲的異常;拋是指程式碼執行出現異常,將會在異常處生成一個對應的異常類物件,並將此物件跑出給方法的呼叫者。三種方式來處理,第一種時try-catch-finally(finally為可選),第二種是在方法定義的後面追加throws xxException,其中try-catch-finally是在此處真正處理掉異常的,以後如果再有方法呼叫這個異常程式碼塊直接呼叫即可,不用做處理;而throws xxException形式的處理方式,只是單純的丟擲異常,並未做實際處理,所以沒有隻要有方法呼叫這個異常程式碼塊還是要做異常處理,因為這個異常程式碼處理異常的方式是將異常拋給方法的呼叫者了。第三種是自定義異常類,用關鍵字throw手動丟擲,如下兩個程式碼段:

        Scanner is = new Scanner(System.in);
        try {
            int s = is.nextInt();
            System.out.println(s);
        } catch (InputMismatchException e) {
            System.out.println("型別轉換出錯了!");
        } finally {
        System.out.print("我是finally");
        }

再看

public
class TestExceptionWithThrows { //這裡mian()方法接收到method2丟擲的異常,需要對他進行處理,如果這裡在採用throws的繼續往上丟擲的話 //那麼異常將會拋給JVM來處理,但是可以看出throws這樣的宣告式的丟擲異常的方式並不是處理異常最根本的方法,最根本的方法應該 //是try-catch這樣的方式,而且如何在異常程式碼塊已經執行了try-catch方式處理過後,那麼呼叫它的方法將不用再最它的異常進行處理 //不想throws方式不斷往上丟擲,上一級還要不斷的對下一級的異常進行處理 public static void
main(String[] args){ try { method2(); } catch (FileNotFoundException e) { System.out.println(e.getMessage()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //這裡method()方法將異常拋給了method2(),然後這裡method2()也是採用throws的方式將異常往上一級丟擲 public static void method2 () throws FileNotFoundException,IOException { method(); } //這裡將異常拋給呼叫者 public static void method() throws FileNotFoundException,IOException { FileInputStream fis = new FileInputStream(new File("hellow.text")); int b; while((b = fis.read())!=-1){ System.out.println((char)b); } fis.close(); } }

其中finally中的程式碼無論是否發生異常,都肯定會執行的,而且注意他們的執行順序是先執行try{}中的程式碼塊,如何發生異常,那麼直接跳到finlly{}的程式碼塊,先執行finally中的程式碼塊,然後再返回來處理異常,執行catch{}中的程式碼塊,如果沒有finally{}程式碼塊,則先處理異常再執行後續程式碼,並且如果有多個異常,那麼catch的時候,就會從上到下的尋找對應的異常處理方式,處理完退出catch塊,並且這裡注意多個catch()中的異常順序從上到下必須是範圍小的異常到範圍大的異常。如

catch(FileNotFoundException e){

}catch(Exception e){

}

這裡看一下綜合程式碼

public class ReturnExceptionDemo {

    static void methodA() {
        try{
            System.out.println("進入方法A");
            //手動丟擲一個異常
            throw new RuntimeException("製造異常");
        } finally {
            System.out.println("呼叫A方法的finally");
        }
    }

    static void methodB() {
        try{
            System.out.println("進入方法B");
            return;
        } finally {
            System.out.println("呼叫B方法的finally");
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            methodA();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        methodB();
    }

}

它的執行結果為:
進入方法A
呼叫A方法的finally
製造異常
進入方法B
呼叫B方法的finally

這裡需要注意的還有就是當try{}程式碼塊中有return時,finally{}塊中的程式碼還是會執行,執行後才會執行return,執行完return之後該方法將會被銷燬。

這裡除了手動丟擲已存在的異常,我們還可以自定義異常,自定的異常一定要繼承已有的異常類,如Exception或者RuntimeException,然後重寫父類的構造方法,一般只要重寫一下(String msg, Throwable)和(String msg)就可以了,其他都不需要動,如下:

//自定義的異常類,必須繼承現有的異常類,提供幾個過載的構造器即可
public class MyException extends RuntimeException {

    private static final long serialVersionUID = 1L;


    public MyException(String message, Throwable cause) {
        super(message, cause);
        // TODO Auto-generated constructor stub
    }

    public MyException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }

}

呼叫異常

/**
 * 手動丟擲異常,自定義異常的資訊
 * @author Weiguo Liu
 *
 */
public class TestExceptionWithHand {

    public static void main(String[] args) {
        Circle c1 = new Circle(2.1);
        Circle c2 = new Circle(2.1);
        System.out.println(c1.compareTo(c2));
        System.out.println(c1.compareTo(new String ("asda")));
    }
}   

class Circle {
    private double radius;//圓的半徑

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public Circle(double radius) {
        super();
        this.radius = radius;
    }

    public int compareTo(Object obj) {
        if(this == obj) {
            return 0;
        }else if(obj instanceof Circle){
            Circle c = (Circle)obj;
            if(this.radius>c.radius){
                return 1;
            }else if(this.radius == c.radius){
                return 0;
            }else{
                return -1;
            }
        }else{
            //手動的丟擲異常
            throw new MyException("傳入的型別有誤!");
        }
    }

}

這裡有一點需要注意的是,如果手動丟擲異常的話,即throw new xxException,那麼必須對這個異常進行try-catch或者在方法後面throws xxException,否則編譯不能通過。