我们看一下应用程序开发中两类比较常见的异常情况,第一类是诸如数据库无法链接,配置文件不存在,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教程