异常是一种特殊的类,在创建异常时会保存创建时的方法调用堆栈镜像。即,为了保留异常出现时的实时堆栈信息,不应复用异常,每个异常均需单独new方式生成。

  下面演示一段有问题的代码并进行分析

  1、问题代码

  a)自定义异常定义

  1. package demo.bce;  
  2. public class MyException extends RuntimeException {  
  3.     private static final long serialVersionUID = -3802919537257556719L;  
  4.     private String id;  
  5.     public MyException(String id) {  
  6.        super();  
  7.        this.id = id;  
  8.     }  
  9.     public String getId() {  
  10.        return id;  
  11.     }  
  12.     public void setId(String id) {  
  13.        this.id = id;  
  14.     }  
  15.     @SuppressWarnings("unused")  
  16.     private MyException() {  
  17.     }  
  18. }

  b)自定义异常常量

  1. package demo.bce;  
  2.    
  3. public final class MyExceptionContext {  
  4.    
  5.     // x1,x2,y1,y2的Throw相关堆栈信息在创建时一次性生成(不再变化) 
  6.     // 即使用此异常会得到错误的堆栈描述信息 
  7.     public static final MyException x1 = new MyException("X1");  
  8.     public static final MyException x2 = new MyException("X2");  
  9.    
  10. }

 c)测试代码

  package demo.bce;

  1. public class MyMain {  
  2.     public static void main(String[] args) {  
  3.        testx();  
  4.     }  
  5.     // /// 
  6.     private static void testx() {  
  7.        try {  
  8.            x11();  
  9.        } catch (Exception e) {  
  10.            e.printStackTrace();  
  11.        }  
  12.        try {  
  13.            x12();  
  14.        } catch (Exception e) {  
  15.            e.printStackTrace();  
  16.        }  
  17.        try {  
  18.            x21();  
  19.        } catch (Exception e) {  
  20.            e.printStackTrace();  
  21.        }  
  22.        try {  
  23.            x22();  
  24.        } catch (Exception e) {  
  25.            e.printStackTrace();  
  26.        }  
  27.     }  
  28.     private static void x11() {  
  29.        throw MyExceptionContext.x1;  
  30.     }  
  31.     private static void x12() {  
  32.        throw MyExceptionContext.x2;  
  33.     }  
  34.     private static void x21() {  
  35.        throw MyExceptionContext.x1;  
  36.     }  
  37.     private static void x22() {  
  38.        throw MyExceptionContext.x2;  
  39.     }  
  40. }