標籤:rgs 越界 long 假設 ble ati alt 封裝 描述
異常是程式運行過程過程出現的錯誤,在Java中用類來描述,用對象來表示具體的異常。 Java將其區分為Error與Exception,Error是程式無法處理的錯誤,Exception是程式可以處理的錯誤。 異常處理是為了程式的健壯性。
Thorwable類是所有異常和錯誤的超類,有兩個子類Error和Exception,分別表示錯誤和異常。 其中異常類Exception又分為運行時異常(RuntimeException)和非運行時異常, 這兩種異常有很大的區別,也稱之為非檢測異常(Unchecked Exception)和檢測異常(Checked Exception)
下面來通過代碼直觀地看一下這兩者的差別:
檢查異常:
如所示,如果不對紅線所存在的異常進行處理,該代碼是無法通過編譯的。必須對其進行throws或者try-catch:
如所示,對兩個異常進行了try-catch處理,代碼可以正常編譯。那麼這樣的異常(FileNotFoundException和IOException)就叫作檢查異常,也叫作非運行時異常,意思是在編譯前就應該對該異常進行處理,否則無法通過編譯。
非檢查異常:
如所示,出現了ArrayIndexOutOfBoundException,這個異常是編譯成功,運行時出現的異常,顧名思義,該異常意思是數組角標越界了,由於該異常是在運行時出現的異常,所以此類異常也叫作運行時異常,或非檢查異常。類似的異常還有NullPointerException等。
自訂異常:
上面出現的幾種異常不管是什麼類型,都是Throwable的間接子類,都已經封裝完畢,我們直接使用就行,但有時候我們系統根據需求會出現各種各樣的異常,這時候就要自訂異常對象了。自訂異常,也是將異常進行封裝,說白了就是用一個自訂的類對異常資訊進行封裝,該類繼承Exception,只需要複寫父類的構造方法即可,通過super將資訊傳入到參數。先來看看父類的構造是如何?的:
Exception:
Throwable:
這就很明顯了,我們在自訂異常類時,在構造方法中用super調用了該類的父類Exception中的構造方法,並將參數傳入,在Exception中用super調用父類Throwable中的構造方法,並將參數傳入,並將該實參值賦值給該類的detailMessage屬性,在getMessage()方法中擷取該值,所以也就有了"myException.getMessage()"(下文會提到)了,可以看得出來這個方法其實是調用的Throwable類中的方法。
假設當前有個需求:對於使用者輸入的使用者名稱進行檢測,如果使用者名稱不是“張三”,則拋出我們自訂的異常對象myException,並列印異常資訊。
自訂的異常類:
1 public class MyException extends Exception{2 3 private static final long serialVersionUID = 1041819209403514525L;4 5 public MyException(String message) {6 super(message);7 }8 }
controller層:
1 public class UserController {2 private UserService userService = new UserService();3 4 public User queryUser(String name,String password) throws MyException {5 return userService.queryUser(name,password);6 }7 }
service層:
1 public class UserService {2 private UserDao userDao = new UserDao();3 public User queryUser(String name, String password) throws MyException {4 return userDao.queryUser(name,password);5 }6 }
dao層:
1 public class UserDao { 2 3 public User queryUser(String name, String password) throws MyException { 4 if (!"張三".equals(name)) { 5 throw new MyException("輸入的密碼或者使用者名稱錯誤"); 6 } 7 8 User user = new User(); 9 user.setUsername(name);10 user.setPassword(password);11 12 return user;13 }14 }
測試:
1 public class Test { 2 3 public static void main(String[] args) { 4 UserController userController = new UserController(); 5 try { 6 User user = userController.queryUser("張大三", "111"); 7 System.out.println(user); 8 } catch (MyException myException) { 9 System.out.println(myException.getMessage());10 }11 12 }13 }
如所示:在測試類別中調用controller中的方法queryUser(String name,String password)來查詢使用者,該方法內部調用的是service層的queryUser(String name,String password)方法,service中的該方法內部調用的是dao層的queryUser(String name,String password)方法,在dao層的該方法內部,對方法參數進行了判斷,如果參數滿足某條件就出現異常,將該異常拋出,並在方法聲明部分進行throws聲明,告知調用該方法的對象,該方法可能存在異常,你要調用,就要對其處理,至於處理的方法取決於調用者,要麼直接在方法聲明部分throws拋出,交給更上一層,要麼進行try-catch,那麼當前的調用者是誰呢,調用dao層該方法的是service層,那麼service層中只是進行了throws,將異常繼續向上拋了,同理,調用service的是controller,controller同樣也是進行了throws,那麼在測試類別Test中調用controller層的方法,進行了try-catch處理,對可能出現異常的代碼進行try,如果監聽到的異常和catch捕獲的異常對象對應,那麼就對其處理,此處處理只是簡單列印異常資訊:
Java中的異常