1. java的异常体系结构
可以看出,java的非正常情况分为Error和Exception,全都继承自父类Throwable。Exception又分为RuntimeException和非运行时异常(也成为Checked Exception)。
Error一般指的是与虚拟机相关的问题,如虚拟机崩溃,动态链接失败,Out of Memory,Thread Death等等。这种错误无法捕获,应用程序也无法处理这种错误。这种错误会导致应用程序中断。
运行时异常属于RuntimeException的子类,例如NullPointerException,IndexOutOfBoundsException等。这些异常一般是由代码逻辑错误引起的,在程序中可以捕获处理,也可以不处理。
非运行时异常属于Exception的子类,如IOException,SQLException等。这些异常从程序语法角度来讲是必须处理的,否则程序编译会出错。
2. 访问异常信息
2.1 getMessage():返回异常的详细描述字符串。
2.2 printStackTrace():将该异常的跟踪栈信息输出到标准输出。
2.3 printStackTrace(PrintStream s):将该异常的跟踪栈信息输出到指定流。
2.4 getStackTrace():返回该异常的跟踪栈信息。
3. 自定义异常
自定义异常都要继承Exception类,如果需要自定义Runtime异常,则需要继承RuntimeException。自定义异常一般需要两种构造器,带参数的和不带参数的。
class SelfException extends Exception { public SelfException() {} //不带参数的构造器 public SelfException(String msg) { //带参数的构造器 super(msg); } }
这种情况比较常用,是因为有可能一个异常不是一个方法就可以处理完的。有时一个方法只能处理一个异常的一部分,因此在捕获该异常的时候还要抛出一个异常交给另外的方法继续处理。
public class Temp { public static void main(String[] args) throws SelfException{ //方法必须抛出该异常 int a [] = new int [5] ; try { a[10] = 1; //JVM会打印出自定义异常信息:Exception in thread "main" SelfException: 数组越界异常!at Temp.main(Temp.java:7) }catch(Exception e) { throw new SelfException("数组越界异常!"); //手动抛出一个自定义异常 } } } class SelfException extends Exception { public SelfException() {} //不带参数的构造器 public SelfException(String msg) { //带参数的构造器 super(msg); } }
5. 异常链
对于真实的企业级应用而言,常常有严格的层次关系,上层功能实现严格依赖下层API。如果底层数据发生了一个SQLException,如果把这个异常原封不动的传给最上层的用户层,是不负责任的表现。因此通常的做法是:程序先捕获原始异常,然后抛出一个新的异常,新的异常中也包含了原始异常的信息,并包含了对用户的提示信息。这种捕获一个异常然后接着抛出另外一个异常,并把原始异常信息保存下来的方法是一种典型的链式处理模式(23中设计模式之一:职责连模式),也成为异常链。在JDK1.4后,所有Throwable的子类在构造器中都可以接受一个cause对象作为参数,这个cause对象就是原始异常对象。这样就可以把原始异常传递给新的异常。
public class Temp { public static void main(String[] args) { //方法必须抛出该异常 try { new Temp().execute(); } catch (SelfException e) { System.out.println(e.getCause()); //使用getCause()方法返回原始异常 } } public void execute () throws SelfException { int a [] = new int[5]; try { a[10] = 1; }catch(Exception e) { throw new SelfException(e); //抛出一个新的异常,参数是原始异常 } } } class SelfException extends Exception { public SelfException() {} //不带参数的构造器 public SelfException(String msg) { //带String参数的构造器 super(msg); } public SelfException(Throwable t) { //带cause参数的构造器 super(t); } }