在設(shè)計一個新的異常類時,首先看看是否真正的需要這個異常類。一般情況下盡量不要去設(shè)計新的異常類,而是盡量使用java中已經(jīng)存在的異常類。
如: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方法中調(diào)用methodA時,ExceptionA是無法處理的,所以ExceptionA應(yīng)該繼續(xù)往上拋出。一個辦法是把methodB聲明會拋出 ExceptionA,但這樣已經(jīng)改變了MethodB的方法簽名。一旦改變,則所有調(diào)用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的產(chǎn)生,這樣才不使異常信息丟失。所以我們在定義一個新的異常類時,必須提供這樣一個可以包含嵌套異常的構(gòu)造函數(shù),并有一個私有成員來保存這個“起因異常”。
代碼如下:
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 }
當然,我們在調(diào)用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
同樣要設(shè)計一個unChecked異常類也與上面一樣。只是需要繼承RuntimeException。
可以參看一些開源框架中的一些通用的異常的設(shè)計,比如Spirng中的NestedCheckedException,Ibatis中的NestedException等,了解更多異常的設(shè)計和處理的信息。