異常
概念
異常是程序運行過程中可能發(fā)生的一類事件。
當方法中發(fā)生錯誤時倡鲸,該方法會創(chuàng)建一個對象——異常對象——并將其交給runtime system(該過程稱為 拋出異常)。
異常對象包含了錯誤信息克滴,包括錯誤發(fā)生時的類型和程序狀態(tài)逼争。
當異常被拋出時劝赔,runtime system會從調(diào)用堆棧里尋找可以處理該異常的方法(exception handler),當找到合適的exception handler時杂伟,即稱為catch the exception仍翰;如果runtime system找不到合適的exception handler,則程序終止予借。
異常的處理與聲明規(guī)則
-
使用
try-catch-finally
語句來捕獲和處理異常-
try
塊包含可能拋出異常的語句catch
塊是異常的接收者,用于處理異常finally
塊包含無論是否發(fā)生異常均需要運行的語句
例如:
public int getNumberFromArray(int[] array, int index) { try { return array[index]; } catch (ArrayIndexOutOfBoundsException e) { System.out.println("數(shù)組越界異常:" + e); } }
-
try-catch-finally
規(guī)則:- 必須在 try 之后添加 catch (至少一個)或 finally 塊秦叛。
- 必須遵循塊順序:若同時使用 catch 和 finally 塊龟再,則順序為:try-catch-finally
- 當一個 try 塊有多個 catch 時,執(zhí)行第一個能匹配的塊利凑。
- 可嵌套 try-catch-finally 結(jié)構(gòu)。
- 在 try-catch-finally 結(jié)構(gòu)中哀澈,可重新拋出異常。
- 除了下列情況膨报,總將執(zhí)行 finally 做為結(jié)束:
- JVM 過早終止(調(diào)用 System.exit(int))适荣;
- 在 finally 塊中拋出一個未處理的異常;
- 計算機斷電弛矛、失火、或遭遇病毒攻擊丈氓。
-
-
使用
throw
語句聲明異常例如:
public int getNumberFromArray(int[] array, int index) throws ArrayIndexOutOfBoundsException { if (index > array.length) { throw new ArrayIndexOutOfBoundsException("數(shù)組越界異常"); } return array[index]; }
-
throw
規(guī)則:- 必須聲明方法可拋出的任何checked exception强法。
- error和runtime exception不是必須聲明的湾笛。
- 調(diào)用方法必須遵循任何checked exception的處理和聲明規(guī)則。聲明的任何異常必須是被覆蓋方法所聲明異常的同類或子類蓖墅。
-
但并非所有異常都適用于上述規(guī)則嘉赎。
三類異常
-
checked exception
該類異常是可預測、可修復的
如:
FileNotFoundException
公条、ArrayIndexOutOfBoundException
checked exceptions適用于前述異常處理與聲明規(guī)則迂曲,該類異常如果沒有經(jīng)過遵循前述規(guī)程的exception handler處理,則會編譯不通過路捧。
-
error
該類異常是發(fā)生于應用程序外部的特例,往往無法預測和修復
如:
IOError
队寇、OutOfMemoryError
errors不適用于前述異常處理與聲明規(guī)則
-
runtime exception
該類異常是發(fā)生于應用程序內(nèi)部的特例章姓,同樣難以預測和修復。該類異常通常表示程序存在bug凡伊,例如邏輯bug或API的不當使用。
如:
NullPointerException
系忙、ArithmeticException
runtime exceptions不適用于前述異常處理與聲明規(guī)則
除以上三種類型外,還可以自定義異常风宁。
常見異常舉例
-
Java.lang.NullPointException
public class Main { public static void main(String[] args) { int[][] arr = new int[2][]; try { arr[0][1] = 1; } catch (NullPointerException e) { System.out.println("發(fā)生異常:" + e.getMessage()); } } } // 輸出: // 發(fā)生異常:null
-
Java.lang.ClassNotFoundException
public class Main { public static void main(String[] args) { try { Class.forName("anotherPackage"); } catch (ClassNotFoundException e) { System.out.println("發(fā)生異常:" + e.getMessage()); } } } // 輸出: // 發(fā)生異常:anotherPackage
-
Java.lang.ArithmeticException
public class Main { public static void main(String[] args) { int a = 1; int b = 0; try { int result = a / b; } catch (ArithmeticException e) { System.out.println("發(fā)生異常:" + e.getMessage()); } } } // 輸出: // 發(fā)生異常:/ by zero
-
Java.lang.ArrayIndexOutOfBoundsException
public class Main { public static void main(String[] args) { int[] arr = new int[4]; try { for (int i = 0; i < arr.length + 1; i++) { arr[i] = 1; } } catch (ArrayIndexOutOfBoundsException e) { System.out.println("發(fā)生異常:" + e.getMessage()); } } } // 輸出: // 發(fā)生異常:4
-
Java.lang.IllegalArgumentException
import java.lang.reflect.Array; public class Main { public static void main(String[] args) { try { int arr = 0; Array.getLength(arr); } catch (IllegalArgumentException e) { System.out.println("發(fā)生異常:" + e.getMessage()); } } } // 輸出: // 發(fā)生異常:Argument is not an array