異常處理垃圾回收
- 什麼是Java異常
- Java 異常是Java提供的用於處理程序中錯誤的一種機制。
- 所謂錯誤是指在程序運行的過程中發生的一些異常事件
- (如:除0溢出,數組下標越界,所要讀取的文件不存在)。
- 設計良好的程序應該在異常發生時提供處理這些錯誤的方法,使得程序不會因爲異常的發生而阻斷或產生不可預見的結果。
- Java程序的執行過程中如出現異常事件,可以生成一個異常類對象,該異常對象封裝了異常事件的信息並將被提交給Java運行時系統,這個過程稱爲拋出(throw)異常。
- 當Java運行時系統接收到異常對象時,會尋找能處理這一異常的代碼並把當前異常對象交給其處理,這一過程稱爲捕獲(catch)異常。
- NullPointerException
- 當應用程序試圖在需要對象的地方使用 null 時,拋出該異常。
- 這種情況包括:
- 調用 null 對象的實例方法。
- 訪問或修改 null 對象的字段。
- 將 null 作爲一個數組,獲得其長度。
- 將 null 作爲一個數組,訪問或修改其時間片。
- 將 null 作爲 Throwable 值拋出。
- ArithmeticException
- 當出現異常的運算條件時,拋出此異常。例如,一個整數“除以零”時,拋出此類的一個實例。
- ArrayIndexOutOfBoundsException
- 用非法索引訪問數組時拋出的異常。如果索引爲負或大於等於數組大小,則該索引爲非法索引。
- ClassCastException
- 當試圖將對象強制轉換爲不是實例的子類時,拋出該異常。
- 案例:
- Object x = new Integer(0);
- System.out.println((String)x);
- RuntimeException
- RuntimeException 是那些可能在 Java 虛擬機正常運行期間拋出的異常的超類。
- 一類特殊的異常,如被0除、數組下標超範圍等,其產生比較頻繁,處理麻煩,如果顯式的聲明或捕獲將會對程序可讀性和運行效率影響很大。因此由系統自動檢測並將它們交給缺省的異常處理程序(用戶可不必對其處理)。
- Exception
- Exception 類及其子類是 Throwable 的一種形式,它指出了合理的應用程序想要捕獲的條件。
- 所有異常類的父類,其子類對應了各種各樣可能出現的異常事件,一般需要用戶顯式的聲明或捕獲。
- Error
- 稱爲錯誤,由 Java 虛擬機生成並拋出,包括動態鏈接失敗、虛擬機錯誤等,程序對其不做處理。
- Throwable
- Throwable 類是 Java 語言中所有錯誤或異常的超類。
- 只有當對象是此類(或其子類之一)的實例時,才能通過 Java 虛擬機或者 Java throw 語句拋出。
- 類似地,只有此類或其子類之一纔可以是 catch 子句中的參數類型。
- 繼承關係的目錄結構如下:
- try
- try代碼段包含可能產生例外的代碼。
- try 代碼段後跟有一個或多個 catch 代碼段。
- 在執行過程中,該段代碼可能會產生並拋出一種或幾種類型的異常對象,它後面的catch語句要分別對 這些異常做相應的處理。
- 如果沒有例外產生,所有的catch代碼段都被略過不執行。
- catch
- 每個catch代碼段聲明其能處理的一種特定類型的異常並提供處理的方法。
- 當異常發生時,程序會中止當前的流程,根據獲取異常的類型去執行相應的catch代碼段。
- 在catch語句塊中是對異常進行處理的代碼,每個try語句塊可以伴隨一個或多個catch語句,用於處理可能產生的不同類型的異常對象。
- 在catch中聲明的異常對象(catch(SomeException e))封裝了異常事件發生的信息,在catch語句塊中可以使用這個對象的一些方法獲取這些信息。
- getMessage( ) 方法,用來得到有關異常事件的信息。
- printStackTrace( ) 方法,用來跟蹤異常事件發生時執行堆棧的內容。
- finally
- finally段的代碼無論是否發生異常都有執行。
- try代碼塊中如果出現return關鍵字,依然會先執行finally代碼塊中的內容,然後執行return。
- finally語句爲異常處理提供一個統一的出口,使得在控制流程轉到程序的其他部分以前,能夠對程序的狀態作統一的管理。
- 通常在finally語句中可以進行資源的清除工作,如:
- 關閉打開的文件
- 刪除臨時文件
- 異常處理示例:
-
try { System.out.println("1"); System.out.println("2"); //int j = 10/0; //System.out.println(j); System.out.println("3"); //Student s = null; //s.sayHello("bff"); System.out.println("4"); return; } catch (ArithmeticException e) { //e.printStackTrace(); System.out.println("捕捉到異常了,異常的信息爲:"); System.out.println(e.getMessage()); } catch (NullPointerException e){ System.out.println("捕捉到異常了,空指針異常,異常的信息爲:"); System.out.println(e.getMessage()); } finally { System.out.println("無論如何都要執行的代碼"); }
-
- 異常的分類:
- 異常分爲受檢查異常(也稱編譯異常)和非受檢查異常(也稱運行時異常)。
- 異常的繼承關係示例圖:
- throw關鍵字:
- 主動產生並拋出異常。
- throws關鍵字:
- 用於在方法定義時聲明可能拋出的異常。
- 示例:
-
public static void main(String[] args) throws Exception { int a = 0; if (a < 1) { throw new Exception("a的值小於1,不符合要求"); } }
-
- 進階示例:
-
public class Demo3 { public static void main(String[] args) { try { m1(); } catch (Exception e) { e.printStackTrace(); } } private static void m1() throws Exception { m2(); } private static void m2() throws Exception { System.out.println("number"); int a = new Scanner(System.in).nextInt(); if (a < 1) { throw new Exception("a的值小於1,不符合要求"); }else{ System.out.println("莫馬達"); } } }
-
- 異常處理的規律:
- 應該先將小異常放在上面,規律先逮小,再逮大。
- 使用自定義異常一般有如下步驟:
- 通過繼承 java.lang.Exception 類聲明自己的異常類。
- 在方法適當的位置 生成自定義異常的實例,並用throw 語句拋出。
- 在方法的聲明部分用throws 語句聲明該方法可能拋出的異常。
- 重寫方法中聲明並拋出異常
- 重寫方法需要拋出與原方法所拋出異常類型一致異常或者 子異常或不拋出異常 或者同時拋出RuntimeException。
- 重點強調
- 可以拋出一個和父類相同的異常類型
- 可以拋出一個比父類小的異常
- 可以拋出比父類更多的異常,但不能拋除了RuntimeException以外的異常
- 可以不拋異常
- 不能拋出比父類更大的異常
- 代碼演示:
-
class A { public void m() throws IOException { } } class B extends A { //可以拋出一個和父類相同的異常類型 /*@Override public void m() throws IOException { super.m(); }*/ //可以不拋異常 /*@Override public void m(){ }*/ //可以拋出一個比父類小的異常 /*@Override public void m() throws FileNotFoundException { }*/ //可以拋出比父類更多的異常 /*@Override public void m() throws FileNotFoundException,NullPointerException { }*/ //不能拋出比父類更大的異常 /*@Override public void m() throws Exception { }*/ }
-
- finalize關鍵字:
- 出處:這是一個來自於Object的方法,所以所有對象都具有該方法
- 作用:一個對象將要被回收時候,最後執行的那個方法
- 如何體現
- 一個類重寫了Object的finalize方法。
- 該對象的引用已經設置爲null。
- 使用System.gc();GC對該對象進行回收,則系統自動調用finalize方法。
- finalize()在什麼時候被調用? 有三種情況
- 所有對象被Garbage Collection時自動調用,比如運行System.gc()的時候。
- 程序退出時爲每個對象調用一次finalize方法。
- 顯式的調用finalize方法。