通用的异常类的设计

在设计一个新的异常类时,首先看看是否真正的需要这个异常类。一般情况下尽量不要去设计新的异常类,而是尽量使用java中已经存在的异常类。

如:IllegalArgumentException, UnsupportedOperationException等。

不管是新的异常是chekced异常还是unChecked异常。我们都必须考虑异常的嵌套问题。

比如:

1 public void methodA() throws ExceptionA{  
2 
3                  
4 
5         throw new ExceptionA();       
6 
7     }

方法methodA声明会抛出ExceptionA.

public void methodB() throws ExceptionB

methodB声明会抛出ExceptionB,当在methodB方法中调用methodA时,ExceptionA是无法处理的,所以ExceptionA应该继续往上抛出。一个办法是把methodB声明会抛出 ExceptionA,但这样已经改变了MethodB的方法签名。一旦改变,则所有调用methodB的方法都要进行改变。另一个办法是把ExceptionA封装成ExceptionB,然后再抛出。如果我们不把ExceptionA封装在ExceptionB中,就丢失了根异常信息,使得无法跟踪异常的原始出处。

代码如下:

 

 1 public void methodB()throws ExceptionB{  
 2 
 3           try{  
 4 
 5               methodA();  
 6 
 7                
 8 
 9            }    catch(ExceptionA ex){  
10 
11               throw new ExceptionB(ex);  
12 
13             }  
14 
15         }

ExceptionB嵌套一个ExceptionA,我们暂且把ExceptionA称为“起因异常”,因为ExceptionA导致了ExceptionB的产生,这样才不使异常信息丢失。所以我们在定义一个新的异常类时,必须提供这样一个可以包含嵌套异常的构造函数,并有一个私有成员来保存这个“起因异常”。

代码如下:

  

1 public Class ExceptionB extends Exception{  
 2 
 3         private Throwable cause;  
 4 
 5            
 6 
 7         public ExceptionB(String msg, Throwable ex){  
 8 
 9             super(msg);  
10 
11             this.cause = ex;  
12 
13         }  
14 
15            
16 
17         public ExceptionB(String msg){  
18 
19             super(msg);  
20 
21         }  
22 
23        
24 
25         public ExceptionB(Throwable ex){  
26 
27             this.cause = ex;  
28 
29         }  
30 
31     }

当然,我们在调用printStackTrace方法时,需要把所有的“起因异常”的信息也同时打印出来。所以我们需要覆写printStackTrace方法来显示全部的异常栈跟踪。包括嵌套异常的栈跟踪。

代码如下:

 1 public void printStackTrace(PrintStrean ps){  
 2 
 3         if(cause == null){  
 4 
 5             super.printStackTrace(ps);  
 6 
 7         }else{  
 8 
 9             ps.println(this);  
10 
11             cause.printStackTrace(ps);  
12 
13         }  
14 
15     }  

一个完整的支持嵌套的checked异常类源码如下。我们在这里暂且把它叫做NestedException

 1 public class NestedException extends Exception {
 2 
 3     private Throwable cause;
 4 
 5     public NestedException(String msg) {
 6 
 7         super(msg);
 8 
 9     }
10 
11     public NestedException(String msg, Throwable ex) {
12 
13         super(msg);
14 
15         this.cause = ex;
16 
17     }
18 
19     public Throwable getCause() {
20 
21         return (this.cause == null ? this : this.cause);
22 
23     }
24 
25     public getMessage() {
26 
27         String message = super.getMessage();
28 
29         Throwable cause = getCause();
30 
31         if (cause != null) {
32 
33             message = message + ";nested Exception is " + cause;
34 
35         }
36 
37         return message;
38 
39     }
40 
41     public void printStackTrace(PrintStream ps) {
42 
43         if (getCause == null) {
44 
45             super.printStackTrace(ps);
46 
47         } else {
48 
49             ps.println(this);
50 
51             getCause().printStackTrace(ps);
52 
53         }
54 
55     }
56 
57     publicvoid printStackTrace(PrintWrite pw) {
58 
59         if (getCause() == null) {
60 
61             super.printStackTrace(pw);
62 
63         } else {
64 
65             pw.println(this);
66 
67             getCause().printStackTrace(pw);
68 
69         }
70 
71     }
72 
73     public void printStackTrace() {
74 
75         printStackTrace(System.error);
76 
77     }
78 
79 }
80 
81 

同样要设计一个unChecked异常类也与上面一样。只是需要继承RuntimeException

可以参看一些开源框架中的一些通用的异常的设计,比如Spirng中的NestedCheckedExceptionIbatis中的NestedException等,了解更多异常的设计和处理的信息。

posted on 2008-05-07 17:30 云淡风清 阅读(655) 评论(0)  编辑  收藏 所属分类: Java


只有注册用户登录后才能发表评论。


网站导航:
 
<2008年5月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

常用链接

留言簿(1)

随笔分类(15)

随笔档案(15)

收藏夹(1)

搜索

最新评论

阅读排行榜

评论排行榜