1. 程式人生 > >Java異常之try,catch,finally,throw,throws

Java異常之try,catch,finally,throw,throws

你能區分異常和錯誤嗎?

我們每天上班,正常情況下可能30分鐘就能到達。但是由於車多,人多,道路擁擠,致使我們要花費更多地時間,這就是生活中的異常!

程式和生活一樣都會出現異常,先來看個異常:


 
上面出現的是算數錯誤的異常。

在java中,除去一些編譯上的錯誤(語法)之外,就有異常和錯誤!

異常的定義是可自己進行處理後,程式依然可以正常執行下去!錯誤是Java虛擬機器丟擲的,終止程式的執行,這就是程式和異常的區別。
 

一:什麼是異常處理?

異常處理機制就像我們對平時可能遇到的意外情況,預先想好了一些處理的辦法。也就是說,在程式執行程式碼的時候,萬一發生了異常,程式會按照預定的處理辦法對異常進行處理,異常處理完畢後,程式繼續執行。
java的異常處理是通過5個關鍵字來實現的:try、catch、finally、throw、throws。
 

二:java異常類的層次結構

三.常見的異常型別

Exception                                          異常層次結構的根類
ArithmeticException                            算數錯誤情形
ArrayIndexOutOfBoundsException       陣列下標越界
NullPointerException                           嘗試訪問null物件成員
ClassNotFoundException                     不能載入所需的類
InputMismatchException                     欲得到的資料型別與實際輸入的型別不匹配
IllegalArgumentException                    方法接受到非法引數
ClassCastException                            物件強制型別轉換出錯
NumberFormatException                     數字格式轉換異常
 

四.具體例項

  • try—catch
package Test;

import java.util.Scanner;

public class Test_Test {
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        System.out.println("請輸入被除數:");
        try {
            int num1=input.nextInt();
            System.out.println("請輸入除數:"
); int num2=input.nextInt(); System.out.println(String.format("%d / %d = %d", num1, num2, num1 / num2)); }catch (Exception e) { System.err.println("出現錯誤:被除數和除數必須是整數,"+ "除數不能為零。"); System.out.println(e.getMessage()); } }

執行結果如下:

System.err.println();這種輸出方式可以輸出錯誤的訊息,在控制檯呈現紅色。
System.out用於正常的輸出,也就是程式真正想輸出的內容。而System.err用於出錯資訊的輸出,也就是你本來不期待看到的東西。

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

這行的作用是——返回該錯誤的詳細資訊的字串。

  • try-catch-finally
package Test;

import java.util.Scanner;

public class Test_Test {
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        System.out.println("請輸入被除數:");
        try {
            int num1=input.nextInt();
            System.out.println("請輸入除數:");
            int num2=input.nextInt();
            System.out.println(String.format("%d / %d = %d",
                    num1, num2, num1 / num2));
        }catch (Exception e) {
            System.err.println("出現錯誤:被除數和除數必須是整數,"+
        "除數不能為零。");
            System.out.println(e.getMessage());
        }
            finally{
            System.out.println("Thanks");
        }
    }
}

執行結果如下:

try-catch-finally 程式塊的流程大致分為兩種情況:
1. 如果try塊中所有語句正常執行完畢,那麼finally塊就會被執行。
2. 如果try語句在執行過程中碰到異常,無論這種異常能否被catch塊捕獲到,都將執行finally塊中的程式碼。

try-catch-finally結構中try塊是必須有的,catch和finally塊為可選,但兩者至少必須出現其中之一。
 
- try—catch-catch-finally(多重catch塊)

package Test;

import java.util.InputMismatchException;
import java.util.Scanner;

public class Test_Test {
    public static void main(String[] args) {
        Scanner input =new Scanner(System.in);
        System.out.println("請輸入被除數:");
        try {
            int num1=input.nextInt();
            System.out.println("請輸入除數:");
            int num2=input.nextInt();
            System.out.println(String.format("%d / %d = %d",
                    num1, num2, num1 / num2));
        }catch (InputMismatchException e) {
            System.err.println("被除數和除數必須是整數。");
        }
         catch (ArithmeticException e) {
                System.err.println("除數不能為零。");
         }
        catch (Exception e) {
            System.err.println("其他未知異常。");
            System.out.println(e.getMessage());
        }
            finally{
            System.out.println("Thanks");
        }
    }
}

執行結果如下:


 
所以,在寫異常處理的時候,一定要把異常範圍小的放在前面,範圍大的放在後面,Exception這個異常的根類一定要剛在最後一個catch裡面,如果放在前面或者中間,任何異常都會和Exception匹配的,就會報已捕獲到…異常的錯誤。
 
下面是try-catch-finally中包含return的情況:
- 情況一:try{} catch(){}finally{} return;

            
正常按程式順序執行即可。

package Test;

public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 1;
        try
        {
            x++;
            System.out.println("我有用!");
        }
        catch (Exception e) {
            System.out.println("我沒用!");
        }
        finally
        {
            ++x;
            System.out.println("我也有用!");
        }
        return 2;
    }
}

執行結果如下:


 
- 情況2:try{ return; }catch(){} finally{} return;

          
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼;         再執行finally塊,最後執行try中return;         finally塊之後的語句return,因為程式在try中已經return所以不再執行。

package Test;

public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 1;
        try
        {
            x++;
            System.out.println("我有用!");
            return 6;
        }
        catch (Exception e) {
            System.out.println("我沒用!");
        }
        finally
        {
            ++x;
            System.out.println("我也有用!");
        }
        return 2;
    }
}

執行結果如下:


 
- 情況3:try{} catch(){return;} finally{} return;

         
程式先執行try,如果遇到異常執行catch塊,         有異常:則執行catch中return之前(包括return語句中的表示式運算)程式碼,再執行finally語句中全部程式碼,                     最後執行catch塊中return. finally之後也就是4處的程式碼不再執行。         無異常:執行完try再finally再return.
 
1.有異常的情況:

package Test;

public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 5;
        try
        {
            int num=x / 0;
            System.out.println(num);
        }
        catch (ArithmeticException e) {
            System.err.println("除數不能為0!");
            return 6;
        }
        finally
        {
            ++x;
            System.out.println("finally");
        }
        return 2;
    }
}

執行結果如下:

2.無異常的情況:

package Test;

public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 5;
        try
        {
            System.out.println("try");
        }
        catch (ArithmeticException e) {
            System.err.println("除數不能為0!");
            return 6;
        }
        finally
        {
            ++x;
            System.out.println("finally");
        }
        return 2;
    }
}

執行結果如下:


 
 
- 情況4:try{ return; }catch(){} finally{return;}

         
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼;          再執行finally塊,因為finally塊中有return所以提前退出。

package Test;

public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 5;
        try
        {
            int num = x / 0;
            System.out.println("try");
            return 3;
        }
        catch (ArithmeticException e) {
            System.err.println("除數不能為0!");
        }
        finally
        {
            ++x;
            System.out.println("finally");
            return 2;
        }
    }
}

執行結果如下:


 
- 情況5:try{} catch(){return;}finally{return;}

         
程式執行catch塊中return之前(包括return語句中的表示式運算)程式碼;          再執行finally塊,因為finally塊中有return所以提前退出。

package Test;

public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 5;
        try
        {
            int num = x / 0;
            System.out.println("try");
        }
        catch (ArithmeticException e) {
            System.err.println("除數不能為0!");
            return 4;
        }
        finally
        {
            ++x;
            System.out.println("finally");
            return 2;
        }
    }
}

執行結果如下:


 
情況6:try{ return;}catch(){return;} finally{return;}

         
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼;          有異常:執行catch塊中return之前(包括return語句中的表示式運算)程式碼;                       則再執行finally塊,因為finally塊中有return所以提前退出。          無異常:則再執行finally塊,因為finally塊中有return所以提前退出。
1.有異常

package Test;

public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 5;
        try
        {
            int num = x / 0;
            System.out.println("try");
            return 4;
        }
        catch (ArithmeticException e) {
            System.err.println("除數不能為0!");
            return 4;
        }
        finally
        {
            ++x;
            System.out.println("finally");
            return 2;
        }
    }
}

執行結果如下:


 
2.無異常

package Test;
/**
 * Java學習交流QQ群:589809992 我們一起學Java!
 */
public class Test_Test {
    public static void main(String[] args) {
        Test1();
    }

    public static int Test1(){
        int x = 5;
        try
        {
//            int num = x / 0;
//            System.out.println("try");
            return 4;
        }
        catch (ArithmeticException e) {
            System.err.println("除數不能為0!");
            return 4;
        }
        finally
        {
            ++x;
            System.out.println("finally");
            return 2;
        }
    }
}

執行結果如下:

最終結論
任何執行try 或者catch中的return語句之前,都會先執行finally語句,如果finally存在的話。         
如果finally中有return語句,那麼程式就return了,所以finally中的return是一定會被return的。                  
編譯器把finally中的return實現為一個warning。
- throw——丟擲異常

丟擲異常有三種形式,一是throw,一個throws,還有一種系統自動拋異常。
系統丟擲異常:

package Test;

public class Test2 {
    public static void main(String[] args) {
        int a = 5, b =0;  
        System.out.println(5/b); 
    }

}

執行結果如下:


 
throw丟擲異常:
throw是語句丟擲一個異常。語法:throw (異常物件);

package Test;
/**
 * Java學習交流QQ群:589809992 我們一起學Java!
 */
public class Test2 {
    public static void main(String[] args) {
        String s = "abc";  
        if(s.equals("abc")) {  
            throw new NumberFormatException();
        } else {  
            System.out.println(s);  
        }  
    }

}

執行結果如下:


 
- throws——宣告異常

throws是方法可能丟擲異常的宣告。(用在宣告方法時,表示該方法可能要丟擲異常)語法:(修飾符)(方法名)([引數列表])[throws(異常類)]{……}

package Test;

public class Test2 {
    public static void main(String[] args) {
        try {
            Test3();
        } catch (NumberFormatException e) {
            System.err.println("非資料型別不能轉換。");
        }
    }

    public static void Test3() throws NumberFormatException{  
        String s = "abc";  
        System.out.println(Double.parseDouble(s));  
    }  
}

執行結果如下:

如果在一個方法體中丟擲了異常,那麼我們就可以通過throws——宣告異常來通知呼叫者,非常方便。
 
throws表示出現異常的一種可能性,並不一定會發生這些異常;throw則是丟擲了異常,執行throw則一定丟擲了某種異常物件。
 
最後說一句,try-catch-finally雖好用,但是如果是濫用,這樣只是會讓程式的可讀性變的很糟糕,當程式報錯,就無法快速準確的定位了,物盡其用 人盡其才嘛!