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]。
對於上面程式碼,可能會出現下面異常:
- 使用者沒有輸入初始化引數:ArrayIndexOutOfBoundsException
- 使用者輸入的不是數字: NumberFormatException
- 被除數為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區別
- 使用Exception是RuntimeException的父類,使用Exception定義的異常都要求必須使用異常處理,即Exception是受查異常;
而使用RuntimeException定義的異常可以由使用者選擇性的來進行異常處理,即非受查異常。 - 常見的RuntimeException:
ClassCastException(類轉換異常)
IndexOutOfBoundsException(陣列越界)
NullPointerException(空指標)
ArrayStoreException(資料儲存異常,運算元組時型別不一致)
NumberFormatException(數值轉化異常)