異常
Java當中對可能出現異常或者錯誤的的一種描述、信息的對象體現
異常的分類
Throwable
Error: 我們無法處理,例如 內存溢出
Exception: (受檢異常) Exception或者Exception的子類但不是RuntimeException的子類稱爲編譯時異常
RuntimeException (運行時異常 非受檢異常) RuntimeException或者RuntimeException的子類
異常處理的目的: 能夠讓程序繼續執行,同時打印錯誤信息\
JVM處理異常的方式
1.打印錯誤信息
2.終止程序
JVM處理異常不能夠滿足我們的需求,所以需要自己處理異常
處理異常的方式
1.try…catch…finally
2.throws
處理方式的格式:
try {
可能處理出現問題的代碼
} catch(異常類名 異常對象) {
異常發生後的處理方式
} catch(異常類名 異常對象) {
異常發生後的處理方式
} ...
異常處理的執行流程
1.程序執行到 System.out.println(a / b);代碼
2.系統會拋出一個異常對象
創建一個異常對象,並且拋出給開發者
ArithmeticException e = new ArithmeticException("/ by zero");
throw e;
3.代碼進入catch塊進行匹配
Exception ae = e; // 多態
4.匹配成功: 程序會轉入catch塊執行
匹配失敗: 程序交還給JVM處理
注意事項:
1.如果程序在try塊中出現了異常,那麼無論try塊下面有多少行代碼都不會被執行,執行去和catch塊進行匹配
2.異常處理的標準格式
a.能夠顯示處理的儘量顯示處理,提高程序的可讀性
b.程序的最後面一定要加上Exception作爲父類接受一切異常,提高了程序的健壯性
代碼示例
public static void main(String[] args) {
System.out.println("遊戲開始");
int a = 10;
int b = 0;
String s = null;
int[] arr = new int[3];
Object obj = "張三";
try {
// System.out.println(a / b);
// System.out.println(s.equals("abc"));
// arr[4] = 10;
Integer integer = (Integer) obj;
} catch(ArithmeticException ae) {
// System.out.println("出問題了,除數爲0!");
ae.printStackTrace();
} catch(NullPointerException ae) {
// System.out.println("出問題了,對象不能夠爲null!");
ae.printStackTrace();
} catch(ArrayIndexOutOfBoundsException aioobe) {
// System.out.println("出問題,數組越界");
aioobe.printStackTrace();
} catch (Exception e) {
// System.out.println("有問題");
e.printStackTrace();
}
System.out.println("遊戲結束");
}
}
Throwable類
1. 該類是所有異常和錯誤的超類
2. 只有當對象是此類(或其子類之一)的實例時,才能通過 Java 虛擬機或者 Java throw 語句拋出
3. 只有此類或其子類之一纔可以是 catch 子句中的參數類型
異常鏈
Throwable initCause(Throwable cause)
將此 throwable 的 cause 初始化爲指定值。
Throwable getCause()
返回此 throwable 的 cause;如果 cause 不存在或未知,則返回 null
常用方法
Throwable fillInStackTrace() 填充錯誤信息到堆棧中
Throwable getCause()
返回此 throwable 的 cause;如果 cause 不存在或未知,則返回 null。
String getLocalizedMessage() 獲取錯誤信息 detailMessage
String getMessage() 同上
StackTraceElement[] getStackTrace() 獲取堆棧中的錯誤信息
Throwable initCause(Throwable cause)
將此 throwable 的 cause 初始化爲指定值。
void printStackTrace() 輸出錯誤信息到控制檯
void printStackTrace(PrintStream s)
void printStackTrace(PrintWriter s)
輸出錯誤信息到 外界 【瀏覽器 文件 …】
void setStackTrace(StackTraceElement[] stackTrace)
設置將由 getStackTrace() 返回,並由 printStackTrace() 和相關方法輸出的堆棧跟蹤元素。
String toString() 獲取錯誤類的對象描述 類路徑: 錯誤信息
返回此 throwable 的簡短描述。
StackTraccElement 中的常見方法
String getClassName()
返回類的完全限定名,該類包含由該堆棧跟蹤元素所表示的執行點。
String getFileName()
返回源文件名,該文件包含由該堆棧跟蹤元素所表示的執行點。
int getLineNumber()
返回源行的行號,該行包含由該堆棧該跟蹤元素所表示的執行點。
String getMethodName()
返回方法名,此方法包含由該堆棧跟蹤元素所表示的執行點。
int hashCode()
返回此堆棧跟蹤元素的哈希碼值。
boolean isNativeMethod()
如果包含由該堆棧跟蹤元素所表示的執行點的方法是一個本機方法,則返回 true。
throws關鍵字
應用場景:
1.我處理不了
2.我沒有權限處理
3.我不想處理
格式:
[修飾符] 返回值類型 方法名(參數列表) [throws 異常類1,異常類2…]{
}
1.該方法拋出異常類,表示拋出調用者處理,誰調用誰處理
2.一個方法可以拋出多個異常
3.如果一個方法拋出的是一個編譯時異常,那麼必須處理,調用者也必須處理
4.子類繼承父類,重寫方法,拋出的異常不能夠被擴大
代碼示例
public static void main(String[] args) /*throws ArithmeticException */{
System.out.println("Start");
/*try {
method();
} catch (Exception e) {
e.printStackTrace();
}*/
try {
show();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("End");
}
public static void show() throws ParseException {
DateFormat df = new SimpleDateFormat("yyyy");
df.parse("1997");
}
public static void method() throws ArithmeticException, NullPointerException {
test();
}
public static void test() throws ArithmeticException, NullPointerException {
int a = 10;
int b = 0;
System.out.println(a / b);
}
}
class Father {
public void show() throws NullPointerException {
}
}
class Son extends Father {
@Override
public void show() throws NullPointerException {
}
}
throw
throw 和 throws的區別
1.throws是在方法的聲明上,throw在方法體內
2.throws表示異常出現的一種可能性,throw表示一定出現了異常
3.throws表示聲明的是異常類,而throw拋出的是異常對象
4.throws可以拋出多個異常類,而throw只能夠拋出一個異常對象
代碼示例
public static void main(String[] args) throws ParseException {
System.out.println("start");
try {
method();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("end");
}
public static void method() throws ArithmeticException {
int a = 10;
int b = 0;
// 處理方式 一: 規避異常
/*if (b != 0) {
System.out.println(a / b);
}*/
// 處理方式二: 直面異常
if (b == 0) {
// ArithmeticException ae = new ArithmeticException("兄弟,除數不能爲0你不知道啊!");
throw new ArithmeticException("兄弟,除數不能爲0你不知道啊!");
}
System.out.println(a / b);
}
}
finally
finally修飾的代碼塊一定會被執行,除非在執行到finally之前程序異常退出或者調用了系統退出的方法。
finally用於釋放資源,在IO流操作和數據庫操作中會見到。
代碼示例
public static void main(String[] args) {
int a = 10;
int b = 0;
try {
System.out.println(a / b);
} catch (Exception e) {
e.printStackTrace();
// return;
System.exit(0);
} finally {
// 一般用來釋放資源
System.out.println("finally代碼塊被執行");
}
System.out.println("over");
}
}
自定義異常
JDK中提供的異常不能夠完全滿足開發的時候,比如分數在0~100分之外就算異常
這個異常JDK中沒有,需要自定義異常
代碼示例
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("請輸入分數: ");
Double score = input.nextDouble();
try {
System.out.println(isLegalScore(score)? "合法":"不合法");;
} catch (ScoreException e) {
e.printStackTrace();
} finally {
if (input != null) {
input.close();
}
}
System.out.println("批改結束....");
}
/*
* 判斷分數是否在0~100分之間
*/
public static boolean isLegalScore(Double score) throws ScoreException {
if (score < 0 || score > 100) {
throw new ScoreException("兄弟,這個分數是不是改錯了!這個" + score + "不行,0~100分之間纔可以,例如61分,79分");
}
return true;
}
}
class ScoreException extends Exception {
private static final long serialVersionUID = -1989349702073875392L;
public ScoreException() {}
public ScoreException(String message) {
super(message);
}
運行結果: