一. Java 中的異常和 .Net 中的異常。
C# 中的異常處理是很自由的,不需要在方法的簽名中聲明所可能拋出的異常類型,也不強制要求在調用方法時捕獲異常。對於沒有 catch 的異常會一直往上拋,直到被 CLR 處理,程序被中斷。
JAVA 中的異常處理很嚴謹,除了 RuntimeException 或其子類(非檢查性異常),其他異常必須在方法簽名中進行聲明。所有異常必須在程序的某個地點捕捉,否則 JVM 將會退出。
二. Java 異常類層次結構
三. 檢查性異常和非檢查性異常
1. 檢查性異常
在 Java 中所有不是 RuntimeException 派生的 Exception 都是檢查型異常,檢查性異常在編譯階段就暴露出來。
當函數中存在拋出檢查型異常的操作時,該函數的函數聲明中必須包含 throws 語句。調用該函數的函數也必須對該異常進行 try...catch 處理,如不進行處理則必須在調用函數上聲明 throws 語句,如不進行處理則必須在調用函數上聲明 throws 語句。
常見檢查性異常:輸入輸出異常 (IOException)、SQL 語句異常 (SQLException) 等。
2. 非檢查性異常
在 Java中 所有 RuntimeException(RuntimeException派生自Exception) 的派生類都是非檢查型異常,非檢查型異常在運行階段才暴露出來。
當函數中存在拋出非檢查性異常時,可以不用再函數上聲明 throws 語句。調用該函數的函數可以不用在函數上聲明 throws 語句,也可以不使用 try...catch 進行處理。如果有異常產生,則異常將由 JVM 進行處理。
常見非檢查性異常:空指針異常(NullPointerException)、除零異常(ArithmeticException)、數組越界異常(ArrayIndexOutOfBoundsException)、以及用戶自定義的 Exception 異常等。
注:
對於 RuntimeException 的子類最好也使用異常處理機制。雖然 RuntimeException 的異常可以不使用 try...catch 進行處理,但是如果一旦發生異常,則肯定會導致程序中斷執行。
所以,爲了保證程序再出錯後依然可以執行,在開發代碼時最好使用 try...catch 的異常處理機制進行處理。
四. 測試源碼
1. C# 測試源碼
using System; namespace ConsoleApplication3 { class Program { static void Main(string[] args) { // 如果不捕獲異常,則會直接上拋給 CLR 處理,然後程序中斷,後面代碼不會執行 Test test = new Test(); test.ConvertToString(""); // 捕獲異常 try { Test test2 = new Test(); test2.ConvertToString(""); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } public class Test { public int ConvertToString(string msg) { if (msg == null || msg == "") { // 可以直接拋出異常,不需要再函數中聲明異常類型 throw new NullOrEmptyStringException("參數不能爲空"); } return int.Parse(msg); } } public class NullOrEmptyStringException : Exception { private string _message; public NullOrEmptyStringException(string message) { this._message = message; } public override string Message { get { return this._message; } } } }
2. Java 測試源碼
package indi.tracine.jdbc; public class Instance { public static void main(String[] args) { try { String sVal1 = ""; Integer iVal1 = convertTOString1(sVal1); System.out.println(iVal1); } catch (RuntimeException e) { System.out.println(e.getMessage()); } System.out.println("-----------------------------------"); // 運行時異常可以不捕獲,直接拋給 JVM 處理,後面代碼不會再執行 String sVal2 = ""; Integer iVal2 = convertTOString1(sVal2); System.out.println(iVal2); System.out.println("-----------------------------------"); // 檢查性異常必須捕獲調用的函數可能拋出的異常,或者在 函數簽名中聲明 throws Exception try { String sVal3 = ""; Integer iVal3 = convertTOString2(sVal3); System.out.println(iVal3); } catch (Exception e) { System.out.println(e.getMessage()); } System.out.println("-----------------------------------"); // 這裏會編譯失敗 //String sVal4 = ""; //Integer iVal4 = convertTOString2(sVal4); //System.out.println(iVal4); } public static int convertTOString1(String msg) { if (msg == null || msg == "") { // 運行時異常(非檢查性異常)可以不用再函數簽名中聲明 throws throw new RuntimeException("這裏不能爲空"); } int val = Integer.parseInt(msg); return val; } public static int convertTOString2(String msg) throws Exception { if (msg == null || msg == "") { // 檢查性異常,必須在函數簽名中聲明異常類型 throw new Exception("這裏不能爲空"); } int val = Integer.parseInt(msg); return val; } }