1. 程式人生 > >6、java中的異常機制總結

6、java中的異常機制總結

生成 sage 得到 enter 技術分享 結構 lag str 條件語句

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中的異常機制總結