6、java中的異常機制總結
1、異常分類
Java是采用面向對象的方式來處理異常的。處理過程:
1. 拋出異常:在執行一個方法時,如果發生異常,則這個方法生成代表該異常的一個對象,停止當前執行路徑,並把異常對象提交給JRE。
2. 捕獲異常:JRE得到該異常後,尋找相應的代碼來處理該異常。JRE在方法的調用棧中查找,從生成異常方法開始回溯,直到找到相應的異常處理代碼為止。
try { copyFile("d:/a.txt","e:/a.txt"); } catch (Exception e) { e.printStackTrace(); } |
Java對異常進行了分類,不同類型的異常分別用不同的Java類表示,所有異常的根類為java.lang.Throwable,Throwable下面又派生了兩個子類:Error和Exception。Java異常類的層次結構如圖6-2所示。
圖1-1 Java異常類層次結構圖
1、Error表明系統JVM已經處於不可恢復的崩潰狀態中。我們不需要管它。
2、Exception是程序本身能夠處理的異常 Exception類是所有異常類的父類,其子類對應了各種各樣可能出現的異常事件。 通常Java的異常可分為:
1. RuntimeException 運行時異常 運行期間拋出 比如空指針
這類異常通常是由編程錯誤導致的,所以在編寫程序時,並不要求必須使用異常處理機制來處理這類異常,經常需要通過增加“邏輯處理來避免這些異常”。如被 0 除、數組下標越界、空指針、強轉錯誤等,其產生比較頻繁,處理麻煩,如果顯式的聲明或捕獲將會對程序可讀性和運行效率影響很大。 因此由系統自動檢測並將它們交給缺省的異常處理程序(用戶可不必對其處理)。
2. CheckedException 已檢查異常 編譯期間處理 比如io
所有不是RuntimeException的異常,統稱為Checked Exception,又被稱為“已檢查異常”,如IOException、SQLException等以及用戶自定義的Exception異常。 這類異常在編譯時就必須做出處理,否則無法通過編譯。
2、異常的處理方式之一:捕獲異常
try-catch執行流程
多重 catch 語句中,異常類型必須子類在前父類在後
多重 catch 語句中,異常類型必須子類在前父類在後,如果你把父類放前面就執行不到後邊的了,
把子類放前面,因為子類的異常信息比父類更詳細
public static void readMyFile() { FileReader reader = null; try { reader = new FileReader("d:/b.txt"); // 沒有b.txt這個文件的異常 System.out.println("step1"); char c1 = (char) reader.read(); // 文件中讀取不到內容異常 System.out.println(c1);
} catch (FileNotFoundException e) { // 子類異常在父類異常前面 System.out.println("step2"); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { System.out.println("step3"); try { // 如果 沒有b.txt文件 reader為null 可能出現空指針異常 if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } }
} |
3、 異常的處理方式之二:聲明異常(throws子句)
拋到最上層 誰調誰執行
public class Test03 { public static void main(String[] args) throws IOException { readMyFile(); }
public static void readMyFile() throws IOException { //此處這下面異常的最頂層異常 FileReader reader = null; reader = new FileReader("d:/b.txt"); //FileNotFoundException異常 System.out.println("step1"); char c1 = (char) reader.read(); //IOException異常 System.out.println(c1);
if (reader != null) { reader.close(); //IOException異常 } } } |
4、自定義異常
package exception01;
public class Test04 {
public static void main(String[] args) throws IllegalAgeException { Person p = new Person(); p.setAge(-10); } }
class Person { private int age;
public void setAge(int age) throws IllegalAgeException { if (age < 0) { throw new IllegalAgeException("年齡不能為負數"); } this.age = age; }
} // 繼承運行時異常 上面不用處理try-catch or throws // 繼承Exception->不是運行時異常->必須在編譯的時候就處理 class IllegalAgeException extends Exception { public IllegalAgeException() { }
public IllegalAgeException(String message) { super(message); } } |
5、補充說明
1.JDBC關閉連接的時候為什麽要單獨try-catch
把所有關閉語句寫在同一個try塊裏面,一旦前面的關閉語句拋異常,後面的關閉語句就無法執行了,所以不能這樣寫,要給每個關閉語句一個try塊。
//關閉資源 public static void closeAll(ResultSet rs,Statement stmt,Connection conn){ try { rs.close(); } catch (Exception e) {
} try { stmt.close(); } catch (SQLException e) {
} try { conn.close(); } catch (SQLException e) {
} } |
總結:https://www.cnblogs.com/wangyingli/p/5912269.html
1.若一段代碼前有異常拋出,並且這個異常沒有被捕獲,這段代碼將產生編譯時錯誤「無法訪問的語句」。如代碼1
2.若一段代碼前有異常拋出,並且這個異常被try...catch所捕獲,若此時catch語句中沒有拋出新的異常,則這段代碼能夠被執行,否則,同第1條。如代碼2
3.若在一個條件語句中拋出異常,則程序能被編譯,但後面的語句不會被執行。如代碼3
問題總結:
問題1:為什麽在UserServiceImpl中要顯示的創建無參構造方法?
答:因為父類構造器拋出了異常 子類在初始化的時候 子類的構造器會調用父類的構造器(初始化的時候總是先初始化父類) 父類的構造器拋出了異常,子類的構造器在調用父類的構造器時也應該拋出異常(並且該異常可以比父類異常範圍大),若子類不提供構造器,雖然會隱式的生成無參構造器,但是生成的無參構造器不會拋出父類構造器的異常,所以子類必須顯示的聲明無參構造器來拋出此異常。
子類 public class UserServiceImpl extends UnicastRemoteObject implements UserService{
protected UserServiceImpl() throws RemoteException { super(); } } 父類: protected UnicastRemoteObject() throws RemoteException { this(0); } |
問題2:若一個類只有有參構造器,沒有無參構造器,能用反射創建對象嗎?
答:不能,因為反射在創建對象時,必須要走無參構造器。如果是用new關鍵字,則可以直接調用有參構造器創建對象。
問題3:接口為什麽也要拋出異常
答:當實現類在實現接口方法時可能會拋出異常,根據java語法規範,該接口也需要手動拋出對應的異常。
6、java中的異常機制總結