在设计一个新的异常类时,首先看看是否真正的需要这个异常类。一般情况下尽量不要去设计新的异常类,而是尽量使用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中的NestedCheckedException,Ibatis中的NestedException等,了解更多异常的设计和处理的信息。