1. 程式人生 > >Java異常(異常體系 、try catch finally 、Exception ) Exception和RuntimeException區別

Java異常(異常體系 、try catch finally 、Exception ) Exception和RuntimeException區別

首先看一下異常的繼承體系:
在這裡插入圖片描述
所有的異常都是由Throwable繼承而來,我們來看他下面的兩個子類Error和Exception.
Error (棧溢位異常):Error類描述Java執行時內部錯誤與資源耗盡錯誤。應用程式不丟擲此類異常,這種內部錯誤(是JVM內部出現錯誤)一旦出現,除了告知使用者並使程式安全終止之外,別無他法。
在Exception之下又分為兩個分支,RuntimeException和IOException。
RuntimeException(執行時異常):由於程式出現錯誤導致的異常。
IOException :程式本身沒有問題,但由於出現I/O問題導致的異常(比如:開啟一個不存在的檔案)

非受查異常
繼承於Error與RuntimeException類的所有異常子類稱為非受查異常(不強制使用者進行異常處理)

受查異常:
Exception以及IOException子類屬於受查異常(強制使用者進行異常處理,比如在寫程式碼時程式碼那出現紅線)。
如果一個程式出現異常:

package CODE;

public class Exception
{
    public static void main(String[] args)
    {
        System.out.println("1.計算前....");
        System.out.println("2.計算式及結果:"+20/0);
        System.out.println("3.計算完畢");
    }
}

在這裡插入圖片描述
可以看到在出現異常後,異常語句產生之前的語句可以正常執行完畢,而異常產生之後程式直接進行了結束。
異常處理格式:為了保證程式出現異常後,也能正常執行下去,需要進行異常處理。

try{
有可能出現異常的語句 ;
}[catch (異常類 物件) {  
  //可以有多個catch
  //出現異常後的解決方案
} ... ]
[finally {
 //異常的出口,無論是否產生異常,均會執行finally 程式碼塊
 //即使try 或者catch存在return ,也會在try/catch return前執行finally程式碼塊
}]

對於以上三個關鍵字,可以出現的組合:try…catch、try…finally、try…catch…finally
try…catch對異常進行處理:

package CODE;

public class Exception
{
    public static void main(String[] args)
    {
         System.out.println("1.計算前....");
         try  //try裡放可能出現異常的語句
         {
             System.out.println("2.計算式及結果:"+20/0);
         }
         catch(ArithmeticException e) //異常類 異常物件
         {
             System.out.println("分母不能為0");  //出現異常解決方案,告訴使用者分母不能為0
         }
         System.out.println("3.計算完畢");
    }
}

在這裡插入圖片描述
以上程式碼雖然進行了異常處理,但是存在一個問題:你現在根本不知道程式產生了什麼樣的異常。所以為了明確的取得異常資訊,可以直接輸出異常類物件,或者呼叫所有異常類中提供的printStackTrace()方法進行完整異常資訊的輸出。

package CODE;

public class Exception
{
    public static void main(String[] args)
    {
         System.out.println("1.計算前....");
         try  //try裡放可能出現異常的語句
         {
             System.out.println("2.計算式及結果:"+20/0);
         }
         catch(ArithmeticException e) //異常類 異常物件
         {
             e.printStackTrace();
         }
         System.out.println("3.計算完畢");
    }
}

printStackTrace()會把異常完整資訊輸出,會把程式執行完畢,並且告訴使用者出現什麼異常,哪一行出現異常:
在這裡插入圖片描述
如果使用try…catch…finally進行處理:

public class Exception
{
    public static int div(int a,int b)
    {
        System.out.println("1.計算前....");
        try  //try裡放可能出現異常的語句
        {
            System.out.println("2.計算式及結果:"+20/0);
            return 1;

        }
        catch(ArithmeticException e) //異常類 異常物件
        {
            e.printStackTrace();
            return 2;
        }
        finally
        {
            System.out.println("4.finally程式碼塊");
            return 3;
        }
    }

    public static void main(String[] args)
    {

        System.out.println("返回值"+div(10,0)); //返回值是3,也就是說一定會走finally程式碼塊
    }
}

總結:
不管有沒有異常,只有有finally,都會走finally程式碼塊;
即使try 或者catch存在return ,也會在try/catch return前執行finally程式碼塊;
如果finally中有return : 那麼是finally 來return ;
如果finally中沒有return : 如果有異常,則在catch中return ,如果沒有異常,則在try中return (該誰return誰return )

如果通過命令列引數來給定運算元:

public class Exception
{
    public static void main(String[] args)
    {
        System.out.println("1.計算前....");
        try  //try裡放可能出現異常的語句
        {
            int a=Integer.parseInt(args[0]); //將字串轉為整型
            int b=Integer.parseInt(args[1]); //如果字串中含有字母將會有異常
            System.out.println("2.計算式及結果:" + a/b);
        }
        catch(ArithmeticException e) //異常類 異常物件
        {
            e.printStackTrace();
        }
        System.out.println("3.計算完畢");
    }
}

注:在idea中輸入命令列引數:[run]–>[Edit Configurations]—>[program arguments]。
對於上面程式碼,可能會出現下面異常:

  1. 使用者沒有輸入初始化引數:ArrayIndexOutOfBoundsException
  2. 使用者輸入的不是數字: NumberFormatException
  3. 被除數為0:ArithmeticExceptio
    對於這些異常就需要一個一個catch:
public class Exception
{
    public static void main(String[] args)
    {
        System.out.println("1.計算前....");
        try  //try裡放可能出現異常的語句
        {
            int a=Integer.parseInt(args[0]); //將字串轉為整型
            int b=Integer.parseInt(args[1]); //如果字串中含有字母將會有異常
            System.out.println("2.計算式及結果:" + a/b);
        }
        catch(ArithmeticException e)   //分母為0
        {
            e.printStackTrace();
        }
        catch (NumberFormatException e) // 輸入不是數字
        {
            e.printStackTrace();
        }
        catch (ArrayIndexOutOfBoundsException e)  //沒有命令列引數
        {
            e.printStackTrace();
        }
        System.out.println("3.計算完畢");
    }
}

可是事實上並不知道有多少個異常或者catch 異常太繁瑣,如果知道這些的異常的父類,可以直接用父類物件處理異常:

public class Exception1
{
    public static void main(String[] args)
    {
        System.out.println("1.計算前....");
        try  //try裡放可能出現異常的語句
        {
            int a=Integer.parseInt(args[0]); //將字串轉為整型
            int b=Integer.parseInt(args[1]); //如果字串中含有字母將會有異常
            System.out.println("2.計算式及結果:" + a/b);
        }
        catch(Exception e)   //分母為0
        {
            e.printStackTrace();
        }
        System.out.println("3.計算完畢");
    }
}

Exception和RuntimeException區別

  1. 使用Exception是RuntimeException的父類,使用Exception定義的異常都要求必須使用異常處理,即Exception是受查異常;
    而使用RuntimeException定義的異常可以由使用者選擇性的來進行異常處理,即非受查異常。
  2. 常見的RuntimeException:
    ClassCastException(類轉換異常)
    IndexOutOfBoundsException(陣列越界)
    NullPointerException(空指標)
    ArrayStoreException(資料儲存異常,運算元組時型別不一致)
    NumberFormatException(數值轉化異常)