
出現不可預計的問題時,需要進行如下處理:
- 報告錯誤
- 儲存操作結果
- 允許使用者退出
本章解決的問題:
- 驗證程式正确性
- 記錄程式錯誤
- 調試技巧
11.1 處理異常
程式出現錯誤時應該:
- 傳回安全狀态,能讓使用者執行其他指令
- 允許使用者儲存所有操作結果,并能夠終止程式
程式錯誤的關注點:
- 使用者輸入錯誤
- 不遵循程式要求,文法不正确,程式代碼應該檢查,如果沒有檢查,會出現錯誤(遇到過,沒檢查到,提示不友好使用者投訴的)
- 裝置錯誤
- 硬體不一定能夠使用,比如列印機關上了,沒紙了(這個處理好IO問題不大)
- 實體限制
- 磁盤滿了(遇到過,資料庫太大把磁盤占滿,搬資料庫)
- 代碼錯誤
- 傳回了錯誤的答案,或者錯誤的調用了其他方法(必然遇到過T T)
11.1.1 異常分類
Throwable下,分為Error和Exception
Exception下,又分爲IOException和RuntimeException
Error: Java運作時的内部錯誤和資源耗盡錯誤。這種錯誤通常是系統當機級别的,處理起來時間較長。(比如沒有磁盤空間了)通常在代碼層面無法處理這種錯誤。
RuntimeException: 程式本身沒有問題,IO錯誤等
常見的運作時異常:
- 數組越界
- 空指針
- 類型轉換錯誤
檢查異常:
- 錯誤URL
- 反射異常
- 讀取超出檔案尾部的資料
是以非運作時錯誤,一定是編碼問題
11.1.2 聲明已檢查異常
無法處理的情況,Java方法可以抛出一個異常,告訴編譯器要傳回什麼值,如果沒有值,則傳回發生的錯誤。
抛出異常的情況:
(1)調用抛出異常的方法
(2)運作過程中發生錯誤,抛出已檢查異常
(3)程式錯誤,提供不應該提供的數值,a[-1]=0 會報越界異常
(4)Java 虛拟機和運作庫異常
前兩種必須捕獲,不捕獲可能當機
抛出異常的方式:
Class MyAnimation{
Pubic Image loadImage(String s) throw EOFException,MalformedURLException{}
}
異常處理方式:
捕獲:進行處理,展示給使用者
抛出:交給上一層級處理
不處理:不可控的Error,或者使用規則限制,不産生額外的異常
特殊要求:
子類異常範圍,不能超出父類異常範圍
11.1.3 如何抛出異常
假設IO讀取資料時不完整,可考慮抛出IOException, API 提議抛出 EOFException
基本格式:
public [傳回值] 方法名(參數清單) 抛出清單{
throw new XXException();
}
11.1.4 建立異常類
有時候,标準異常描述并不能做到清楚具體,或者無法具體定位異常原因,為了進一步了解是程式中的哪一段出現異常,可考慮建立自己的異常類(個人覺得一個是名稱識别,另外異常文字之類的可以做特殊處理,讓它列印到log對應級别上而非直接輸出)。
class FileFormatException extends IOException{
public FileFormatException(){}
public FileFormatException(String gripe){
super(gripe);
}
}
然後就可以像IOException一樣使用這種異常
public class Main {
public static void main(String[] args) throws FontFormatException {
Main solution = new Main();
solution.test(1);
}
private void test(int num) throws FontFormatException {
if(num==1)
throw new FontFormatException("test");
}
}
不傳之密,異常處理工具,保留一定字數的異常資訊(資料庫存儲大小是有限的):
public class ErrorUtil {
public static String exceptionStr(Exception e, int length) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(baos));
String exception = baos.toString();
String regEx = "Caused by:(.*)";
Pattern pat = Pattern.compile(regEx);
Matcher mat = pat.matcher(exception);
boolean rs = mat.find();
if (rs) {
if (mat.group(1).length() > length) {
return mat.group(1).substring(0, length);
} else {
return mat.group(1);
}
} else {
if (exception.length() > length) {
return exception.substring(0, length);
} else {
return exception;
}
}
}
public static String exceptionStr(Exception e){
return exceptionStr(e,800);
}
public static String getAllException(Exception e){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(baos));
String exception = baos.toString();
String regEx = "Caused by:(.*)";
Pattern pat = Pattern.compile(regEx);
Matcher mat = pat.matcher(exception);
boolean rs = mat.find();
if (rs) {
return mat.group(1);
} else {
return exception;
}
}
}
結合:
public class Main {
public static void main(String[] args) {
Main solution = new Main();
try {
solution.test(1);
} catch (FontFormatException e) {
System.out.println(ErrorUtil.getAllException(e));
}
}
private void test(int num) throws FontFormatException {
if(num==1)
throw new FontFormatException("test");
}
}