我們看一下應用程序開發中兩類比較常見的異常情況,第一類是諸如數據庫無法鏈接,配置文件不存在,SQL語句編譯錯誤等的系統級別的異常,一旦這種
異常發生基本上系統無法正常運行。另一類是諸如數據庫中的內容不存在,格式不正確,業務邏輯不滿足要求等的異常,這種異常往往只影響某一條的數據,不會對
系統的正常運行有影響。
Java中的兩類異常
Java中的異常分為兩種類型運行時的異常(RuntimeException)和檢查異常(Checked Exception)。
運行時的異常(RuntimeException)可以在程序運行的時候動態的拋出,但是不需要在方法接口中聲明要跑出的運行時異常,也不需要在方
法調用的時候做try-catch處理。系統的運行時異常是指java.lang.RuntimeExceptioin或者他的子類型。
RuntimeException在邏輯上的含義是:
檢查異常(Checked Exception)必須要在方法的接口中聲明,并且在使用方法的時候,其拋出的Checked Exception必須使用try-catch處理,檢查異常指的是java.lang.Exception或者他的子類型。
注意:有一點需要指出,java.lang.RuntimeException是java.lang.Exception的子類型。所以上述中說的
檢查異常(Checked
Exception)指的是java.lang.Exception和其他的非java.lang.RuntimeException子類的子類型。
如下代碼展示了RuntimeException的使用:
package com.jpleasure.exception;
/**
* System Exception
* @author mazhao@dl.cn
*
*/
public class SystemException extends RuntimeException {
public SystemException() {
}
public SystemException(String message) {
super(message);
}
public SystemException(Throwable cause) {
super(cause);
}
public SystemException(String message, Throwable cause) {
super(message, cause);
}
}
以下代碼可以編譯通過,運行的時候拋出異常:
package com.jpleasure.exception;
public class Main {
public static void main(String ... args ) {
testRuntimeException();
}
public static void testRuntimeException() {
methodThrowsRuntimeException();
}
private static void methodThrowsRuntimeException() {
if(true) {
throw new SystemException("Hello World!");
}
}
}
運行的時候輸出內容為:
Exception in thread "main" com.jpleasure.exception.SystemException: Hello World!
at com.jpleasure.exception.Main.methodThrowsRuntimeException(Main.java:17)
at com.jpleasure.exception.Main.testRuntimeException(Main.java:11)
at com.jpleasure.exception.Main.main(Main.java:5)
以下代碼展示了Exception的使用:
package com.jpleasure.exception;
/**
* Application Exception
* @author mazhao@dl.cn
*
*/
public class ApplicationException extends Exception {
public ApplicationException() {
// TODO Auto-generated constructor stub
}
public ApplicationException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public ApplicationException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
public ApplicationException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
}
異常使用代碼:
package com.jpleasure.exception;
public class Main2 {
/**
* @param args
*/
public static void main(String[] args) {
}
public static void testCheckedException() {
try {
methodThrowsCheckedException();
} catch (ApplicationException e) {
// 異常處理代碼
}
}
private static void methodThrowsCheckedException() throws ApplicationException {
if(true) {
throw new ApplicationException("Hello World!");
}
}
}
由于ApplicationException是Checked Exception,所以在方法的接口中必須加以聲明,并且在使用的時候必須包括在try-catch代碼塊中。
應用程序開發中的異常
如上述代碼中說明的那樣處于使用方便我們總是將系統異常設置為RuntimeException的子類,在統一的地方處理。
為什么要將系統異常設置為Runtime的呢?
try-catch塊主要是為了在異常發生的時候有可以挽救的方式,所以會在try部分異常發生的時候進入catch部分,但是系統異常(例如數據
庫無法鏈接,配置文件不存在等)一旦發生基本上沒有挽救的辦法,所以將系統異常聲明為RuntimeException的子類。
另外,系統異常是一種很少會發生的異常,所以在開發中基本不需要考慮,所以將系統異常生命為RuntimeException的子類,這樣在開發的時候基本不需要考慮系統異常發生的情況,只需要統一的做錯誤處理即可。
應用程序異常通常設置為Checked Exception。需要在使用的地方逐個處理。
異常消息定義
異常消息通常不會在構造異常的時候傳入,通常情況下在構造異常的時候傳入的是異常消息的編號。
編號一般包含的內容有:系統ID,子系統ID,消息類型,流水號等。系統ID,子系統ID,流水號等都比較好理解,那么消息類型是什么呢?我們的消
息常見的有以下一些類型:提示性的,警告性的,錯誤性的。所以我們可以分別以C(Confirm),W(Warnning),E(Error)來區分消息
的類型
消息一般存儲在屬性文件(Properties)中使用ResourceBundle類或者Properties類來獲取。當使用到多國語言的錯誤消息的時候需要使用ResourceBundle類。
有些時候也可以存儲在代碼中,這個時候需要使用到ListResourceBundle類。
異常發生時的操作
第一就是要記錄錯誤日志,需要將類,方法,操作數據,異常類型,異常內容的信息記錄下來,便于系統維護人員分析問題數據。
第二及時要拋出錯誤信息,反饋給系統用戶,讓客戶知道系統無法處理他的當前操作。如果有必要還需要提示客戶可能的錯誤情況,希望用戶改善。
如何獲得異常的詳細信息
從異常中可以獲得詳細的拋出信息,例如都那些代碼涉及到這個異常,分別在那些類的那些方法中,代碼行數是多少,代碼文件名字是什么等。
例如類LoginLogic調用了LoginDao,而Main調用了LoginLogic,代碼為:
package com.jpleasure.exception;
/**
* Created by IntelliJ IDEA.
* User: ma.zhao@dl.cn
* Date: 2007-9-3
* Time: 22:55:47
* To change this template use File | Settings | File Templates.
*/
public class LoginDao {
public void testLogin() throws SystemException {
if(true) {
throw new SystemException("System Exception Occurs!");
}
}
}
package com.jpleasure.exception;
import java.util.Random;
/**
* Created by IntelliJ IDEA.
* User: ma.zhao@dl.cn
* Date: 2007-9-3
* Time: 22:56:30
* To change this template use File | Settings | File Templates.
*/
public class LoginLogic {
private LoginDao dao = new LoginDao();
public void testLogin() throws ApplicationException {
Random randam = new Random(System.currentTimeMillis());
int randamInt = randam.nextInt();
if (randamInt % 2 == 0) {
dao.testLogin();
} else {
throw new ApplicationException("Application Exception Occurs!");
}
}
}
異常處理代碼:
package com.jpleasure.exception;
/**
* Created by IntelliJ IDEA.
* User: ma.zhao@dl.cn
* Date: 2007-9-3
* Time: 22:57:38
* To change this template use File | Settings | File Templates.
*/
public class Main {
public static void main(String[] args) {
LoginLogic logic = new LoginLogic();
try {
logic.testLogin();
} catch (ApplicationException e) {
printException(e);
} catch (SystemException e) {
printException(e);
}
}
private static void printException(Exception e) {
String msg = e.getMessage();
System.out.println("exception message:" + msg);
StackTraceElement[] stes = e.getStackTrace();
for (int i = 0; i < stes.length; i++) {
printStackTraceElement(stes[i]);
}
}
private static void printStackTraceElement(StackTraceElement ste) {
String fileName = ste.getFileName();
String className = ste.getClassName();
String methodName = ste.getMethodName();
int line = ste.getLineNumber();
System.out.println("file:" + fileName + "\t class:" + className + "\t method:" + methodName + "\t line:" + line);
System.out.println("");
}
}
ExtJS教程-
Hibernate教程-
Struts2 教程-
Lucene教程