Java异常框架设计

声明
  • 声明: 1、任何网站转载本站点内容时需注明来自JAVA-CN.COM,否则我们有权将根据《互联网著作权行政保护办法》追究其相应法律责任; 2、JAVA中文站社区刊登此文只为传递信息,并不表示赞同或者反对.
什么是异常?
Lbc}(?3P s
'D,T%LLq异常(exception)应该是异常事件(exceptional event)的缩写。
B)FlT cL-/E8R异常定义:异常是一个在程序执行期间发生的事件,它中断正在执行的程序的正常的指令流。 JAVA中文站社区门户 q&] B?;XX]+C
当在一个方法中发生错误的时候,这个方法创建一个对象,并且把它传递给运行时系统。这个对象被叫做异常对象,它包含了有关错误的信息,这些信息包括错误的类型和在程序发生错误时的状态。创建一个错误对象并把它传递给运行时系统被叫做抛出异常。
3Z y4?"I&d]一个方法抛出异常后,运行时系统就会试着查找一些方法来处理它。这些处理异常的可能的方法的集合是被整理在一起的方法列表,这些方法能够被发生错误的方法调用。这个方法列表被叫做堆栈调用(call stack)
6zw6NjW/ JAVA中文站社区门户uB5q$a*U7F*z
运行时系统搜寻包含能够处理异常的代码块的方法所请求的堆栈。这个代码块叫做异常处理器,搜寻首先从发生的方法开始,然后依次按着调用方法的倒序检索调用堆栈。当找到一个相应的处理器时,运行时系统就把异常传递给这个处理器。一个异常处理器要适当地考滤抛出的异常对象的类型和异常处理器所处理的异常的类型是否匹配。异常被捕获以后,异常处理器关闭。如果运行时系统搜寻了这个方法的所有的调用堆栈,而没有找到相应的异常处理器。 JAVA中文站社区门户/y(f4WL|(a} mws+mr
JAVA中文站社区门户Ff/P*V9xt&XV;B&^
  JAVA中文站社区门户3P6?h*J.V

8CF^9rt'xWm-y怎么设计异常框架 JAVA中文站社区门户R%q,i v)N
JAVA中文站社区门户:N z9{h|u?AqA6D;j
任何的异常都是Throwable类(为何不是接口??),并且在它之下包含两个字类Error / Exception,而Error仅在当在Java虚拟机中发生动态连接失败或其它的定位失败的时候,Java虚拟机抛出一个Error对象。典型的简易程序不捕获或抛出Errors对象,你可能永远不会遇到需要实例化Error的应用,那就让我们关心一下Exception JAVA中文站社区门户 [|^G;FO
JAVA中文站社区门户$]2AgOnz
Exception中比较重要的就是RuntimeException-运行时异常(当然这个名字是存在争议的,因为任何的异常都只会发生在运行时),为什么说这个类时很重要的呢?因为它直接关系到你的异常框架的设计,仔细看RuntimeException JAVA中文站社区门户%O|P9]k
JAVA中文站社区门户}FtYQ`*{m7Z
A method is not required to declare in its throws clause any subclasses of RuntimeException that might be thrown during the execution of the method but not caught.
xS*jfv:|H4^
`ptkR/a FM#]p-LWC-可能在执行方法期间抛出但未被捕获的 RuntimeException 的任何子类都无需在 throws 子句中进行声明。  JAVA中文站社区门户2Sc6X2FWNe']
JAVA中文站社区门户'f*J(g~ r2mS1B"g%T
也就是说你的应用应该不去“关心”(说不关心是不服责任的,但只是你不应该试图实例化它的字类)RuntimeException,就如同你不应该关心Error的产生与处理一样!RuntimeException描述的是程序的错误引起来的,因该由程序负担这个责任!( 从责任这个角度看Error属于JVM需要负担的责任;RuntimeException是程序应该负担的责任;checked exception 是具体应用负担的责任
7sf5vN _U{^ JAVA中文站社区门户 T!Ec5@/kz
那就有人会问,那我该关心什么!答案就是除了Error与RuntimeException,其他剩下的异常都是你需要关心的,而这些异常类统称为Checked Exception,至于Error与RuntimeException则被统称为Unchecked Exception.
,{2D#vcuG-F5}PoO JAVA中文站社区门户 JH9U?t M^1}@

_6X!Y,[ky7VN异常的概念就这些了,即使你在网络上搜索也就不过如此,是不是感觉到有点清晰又有点模糊?那么怎么该如何在这样单薄而模糊的概念下设计J2EE的异常框架呢?
AG2X9de$p4R JAVA中文站社区门户!iTA#i4K
JAVA中文站社区门户!w+f` V b%PD$?,|:F
解决方案:J2EE异常框架
gz{3K1I.{ g
T1{&[RkdI2O我们拿一个模拟的例子来说明异常框架的设计过程,比如我们要对外提供doBusiness()这个业务方法 JAVA中文站社区门户(Ax(M_V k r
JAVA中文站社区门户QBWeRN
public void doBusiness() throws xxxBusinessException JAVA中文站社区门户5x!t{]*dzi$G

$j&y"|9X(Uo)T当客户端调用这样的方法的时候应该这样处理异常(包括处理RuntimeException , checked exception) JAVA中文站社区门户eaF{)ZDn(}
记住,无论如何我们都不希望或者确切的说是不应该将RuntimeException这样的异常暴露给客户的,因为他们没有解决这个问题的责任!
B4r~h [e我们暂时将Struts中的某个Action看作时客户端,其中doExecute(....)要调用doBusiness()这个方法
Hq+zI7r+Q.w JAVA中文站社区门户zQ#f%C:h&bI$QP
public void doAction(......)
{ x/_X uI_{
&sW7D*d/H T try
6u*gs4csZ:| { JAVA中文站社区门户]C Ir9g'_[W"o

ma s cI*T4[^  xxx.doBusiness(); JAVA中文站社区门户J R J6^8C#H
 } JAVA中文站社区门户 x q ?|"ph?U
 catch(Exception e)
g']ed1F {
F7?-?5oq5R   if(e instanceof RuntimeException)  
F%w g(LX5g:?   { JAVA中文站社区门户4eM*r([!{S^
    // catch runtime exception JAVA中文站社区门户e.||EOd#P7~H
    // 你可以在这里将捕获到的RuntimeException JAVA中文站社区门户[XG2qm
    // 将异常通知给某个负责此程序的程序员,让他知道他
f}tE }P    // 自己犯了多么低级的错误!
t+qL:u(x+N*Ry:a.~ JAVA中文站社区门户K jl |fQ_Vg B

y,/+zw~!A:{   }else JAVA中文站社区门户$s8j2S J ECj X.O
   {
"rRz G%q%EOu    //checked exception such as xxxBusinessException JAVA中文站社区门户Q,tS]-r1D:Z+G$z
    //将这样的异常暴露给客户显示    
(BR@H2o#c JAVA中文站社区门户$jr Jvk.~.L/i
   }
#D(n&o*~4DBP~MXD+} JAVA中文站社区门户:dB&/4RzPG
 }
0x A.Q&[:T4N}
o"^+M1Aw$JB
.p y(Q(O(I4|R/H&k我们可以这样设计xxxBusinessException
LM4H,?z$G JAVA中文站社区门户7jk HX7A;d_.Q+q j
public class xxxBusinessException extends ApplicationException 
H:q+Ww,p'U}{
&Z/q3y O3qi    public xxxBusinessException(String s){
?_M,DF,Q:Y3j        super(s); JAVA中文站社区门户@a9Esh5^
JAVA中文站社区门户$c L*u^/
}; JAVA中文站社区门户ISvY7@6t{

`$w#}mG;Q c-P:y Nhimport java.io.PrintStream;
i#aQK&H kimport java.io.PrintWriter;
YhBl2rk;ppublic class ApplicationException extends Exception {
/D3iF{{k?       /** A wrapped Throwable */
b^.~3Y)KuE       protected Throwable cause;
7F8b.O^JJ       public ApplicationException() { JAVA中文站社区门户kY XcqFS@K
           super("Error occurred in application.");
]CX)wJ       }
2BIrE$f       public ApplicationException(String message)  { JAVA中文站社区门户3U;Si1Zg ~@o |
           super(message);
*Y$v9A)n c9w)x O#@       } JAVA中文站社区门户/Qh-X l._
       public ApplicationException(String message, Throwable cause)  {
MO!mQ2Q           super(message);
h Z'n n!{a           this.cause = cause; JAVA中文站社区门户W2R#uv0y(WBH
       }
4B/p,JR3Qy h}{       // Created to match the JDK 1.4 Throwable method.
E_/@/Q NLk S       public Throwable initCause(Throwable cause)  {
mk6mQ&S+C0U7P$R(eTC           this.cause = cause;
!S,{w @a-T-d9P           return cause; JAVA中文站社区门户:hg rPm7BO
       } JAVA中文站社区门户? v#yH2C)mDI
       public String getMessage() { JAVA中文站社区门户dU/S,aNv&o/w,U
           // Get this exception's message. JAVA中文站社区门户V*/:iC;h$P
           String msg = super.getMessage(); JAVA中文站社区门户!XWSg3J(/U
           Throwable parent = this;
]Xt9PwA)P6]           Throwable child; JAVA中文站社区门户vq+gD)a3@Vt q+|
           // Look for nested exceptions.
k4]E"d@2k|9J*`           while((child = getNestedException(parent)) != null) {
:cnq}c+s?               // Get the child's message. JAVA中文站社区门户&b:b6xi/@Za+C
               String msg2 = child.getMessage(); JAVA中文站社区门户:e] K6QG}z
               // If we found a message for the child exception, 
,erg#cJiVY0Ln               // we append it. JAVA中文站社区门户 NB-C1K2q9U"o
               if (msg2 != null) { JAVA中文站社区门户'F,? ~M wc)Z,U"t
                   if (msg != null) { JAVA中文站社区门户 I q6J*B S#N6`
                       msg += ": " + msg2; JAVA中文站社区门户V v6x4LeE
                   } else {
OC{'xi2QT[}                       msg = msg2;
uT&D,Wy                   } JAVA中文站社区门户U8edX,|5v-z
               }
S9~4F0K4M`e               // Any nested ApplicationException will append its own JAVA中文站社区门户}fLk nD
               // children, so we need to break out of here. JAVA中文站社区门户g`O5pZ'h
               if (child instanceof ApplicationException) { JAVA中文站社区门户C[g4Ad0Aj b
                   break;
Xzgx7R x!t               }
(Tj scht*^ o               parent = child; JAVA中文站社区门户'nv;yhz;i)G,v
           }
"C'c/mk;^8{|           // Return the completed message. JAVA中文站社区门户F]8kp3dKo
           return msg;
Z*@YPuww(y       }
"e T[|B       public void printStackTrace() { JAVA中文站社区门户 n bs+A a x
           // Print the stack trace for this exception. JAVA中文站社区门户'Z@h9H$gMCX1h
           super.printStackTrace();
jr2Ea0~ /Mf;cG           Throwable parent = this; JAVA中文站社区门户1A7q%R0g#Q
           Throwable child; JAVA中文站社区门户%L,eK'mpgE5w Y,V
           // Print the stack trace for each nested exception. JAVA中文站社区门户u;Sc M}gZ#]
           while((child = getNestedException(parent)) != null) {
X6tF-mDj3/               if (child != null) {
3GRvw[axK` /                   System.err.print("Caused by: "); JAVA中文站社区门户w,DC @ I-xJ
                   child.printStackTrace();
T/CzA:@:e;mTd sS                   if (child instanceof ApplicationException) {
0{1l#Er7^.?m                       break;
u2SN.N7oS8g T_                   } JAVA中文站社区门户:l{2^u/c3^F
                   parent = child; JAVA中文站社区门户4F&fiS9N.O(jU_*q
               } JAVA中文站社区门户}Z;z9o;F6L4O
           } JAVA中文站社区门户,Y&Y!{ mnEG
       } JAVA中文站社区门户7s:D6^Wk ][2p!Bo
       public void printStackTrace(PrintStream s) { JAVA中文站社区门户-UQ^WH'SJ;_Y.C ?
           // Print the stack trace for this exception.
j5qm;[BEq ~           super.printStackTrace(s); JAVA中文站社区门户2V8icH'BE4j
           Throwable parent = this; JAVA中文站社区门户#ny i,|u$m
           Throwable child;
5da/O])U&Sg           // Print the stack trace for each nested exception.
9X`4p g:E$qO{e1Z@4p           while((child = getNestedException(parent)) != null) {
|*bG U/x3vd!ea!V               if (child != null) {
LE*z(T d                   s.print("Caused by: "); JAVA中文站社区门户YD }[m(x f6^
                   child.printStackTrace(s);
Q'q(G;Cds)u                   if (child instanceof ApplicationException) { JAVA中文站社区门户E{PKV%~ g!FV
                       break;
,Wf z a+N ^L                   }
f*@*o ?)] ^2b                   parent = child; JAVA中文站社区门户;Tj,D jtc8ry L8g
               } JAVA中文站社区门户%@s.Au Ei-q
           }
H8a/J mAww       }
.K"W6X Sz_7UE       public void printStackTrace(PrintWriter w) {
P{eR.ES           // Print the stack trace for this exception. JAVA中文站社区门户A{zady
           super.printStackTrace(w); JAVA中文站社区门户},[:eE"]r6J2c
           Throwable parent = this;
&b4~-`#D3d qy!N1|g!v           Throwable child; JAVA中文站社区门户^W,g9F3@;J/yq
           // Print the stack trace for each nested exception.
m7ryq E#_)`8vsd           while((child = getNestedException(parent)) != null) { JAVA中文站社区门户 wa7jS7O#Z;s
               if (child != null) {
6UKJPH-E4W}                   w.print("Caused by: ");
!e;r8P X.cXg |H                   child.printStackTrace(w); JAVA中文站社区门户PK$K%C0V*{2q*X
                   if (child instanceof ApplicationException) { JAVA中文站社区门户lpB R?JQO B OK |
                       break; JAVA中文站社区门户E/W7Eq+V1D3lT#NA
                   } JAVA中文站社区门户G d-l5G~q;o
                   parent = child; JAVA中文站社区门户2[W y:n%W V
               } JAVA中文站社区门户5K8]q-k/c$@
           } JAVA中文站社区门户}X8`]PF X4y*g:V
       } JAVA中文站社区门户k:R+u9v0wP
       public Throwable getCause()  { JAVA中文站社区门户0IH7w?~M.g
           return cause;
7{ k b a5U Vc)E       }
Y#sb2V2Z;ij Y} JAVA中文站社区门户4e{ X)ma
JAVA中文站社区门户j"m/xB/u)gNfd|
而"聪明"的读者肯定要问我那doBusiness()这个业务方法该如何包装异常呢? JAVA中文站社区门户 W0ovs{

W*VdM!iJg2w#_4Z X public void doBusiness() throw xxxBusinessException JAVA中文站社区门户5F)g.~'xxHbL/H
 {
gk0bv m G   try
-@v(R5C{1C:W2j%/   {
-j?W.Av `     execute1(); // if it throw exception1
c$d])[2A'egHM;S
E r*tT5M     exexute2(); // if it throw exception 2 JAVA中文站社区门户8A^:bndh%mL

_ jpx4O6iNz o     .... ..... 
ane$V9}O1l
5i_8]nT.z5M/p cY   } JAVA中文站社区门户'T~];X#L m /k
   catch (exception1 e1) JAVA中文站社区门户*dedG(_
   { JAVA中文站社区门户/~JP[ [3T,k{
    throw new xxxBusinessException(e1); JAVA中文站社区门户h,f3i;D5q1TMz
   } JAVA中文站社区门户9|d~ QR2J5s
   catch(exception2 e2)
|6ks*c(po)c   {
B%VW qNLEY    throw new xxxBusinessException(e2);
$T,ts5uRB:f   }
uU"fo X(MbU Vn6IsI   ........
3K/T1`b|2D` } JAVA中文站社区门户 q }/? @ dPc`2Q!S

t4z+j:[j{l'^ 也可以这样 JAVA中文站社区门户3s|y;MT0QN0s+c:F
JAVA中文站社区门户#j#F8U*QT1/0h
 public void doBusiness() throw xxxBusinessException JAVA中文站社区门户-|j,n*@M d[
 { JAVA中文站社区门户(@+b kqA0m&BpDG
   try JAVA中文站社区门户ZQ0I.E3^Y"X6Y'Q
   {
sUmT1Lv7r_ f     execute1(); // if it throw exception1
6{-Z(aF~
D a0h w?db9O     exexute2(); // if it throw exception 2
l#mf+o8_$MLk
b-S0? JQ     .... .....  JAVA中文站社区门户5jl!p `i'S
JAVA中文站社区门户so"hV+[/O$G
   } JAVA中文站社区门户FiO9zL{(^w%Aq
   catch (Exception e)
]VBU"}f_)d8A   { JAVA中文站社区门户R&CB"JX n
    // 注意很多应用在这里根本不判断异常的类型而一股脑的采用 JAVA中文站社区门户/3Y0s:p2n_
    // throw new xxxBusinessException(e);
O/~8Y1y,t2~%W$x{+n    // 而这样带来的问题就是xxxBusinessException"吞掉了"RuntimeException
^C2lpN1UMM7r    // 从而将checked excption 与unchecked exception混在了一起! JAVA中文站社区门户o`6kh[

c/g.P!}] u    // 其实xxxBusinessException属于checked excpetion ,它根本不应该也不能够理睬RuntimeException
9r7A)ob4l+g(v hd    if(! e instanceof RuntimeException) throw new xxxBusinessException(e);
(M)]E3U4hL i   } JAVA中文站社区门户N?)t"LU+G5d/FS
 } JAVA中文站社区门户3I0U%eW6z?8x

'D ^;a9qVa6|)T JAVA中文站社区门户3J#Z6D)n8EO.Hnk
总结
R!qp,ur 1。JAVA的异常分为两类: checked exception & unchecked excpetion JAVA中文站社区门户1Kw PdK!r
 2。应用开发中产生的异常都应该集成自Exception 但都属于checked excpetion类型 JAVA中文站社区门户5E+~:nf x.l)le]#GE
 3。应用中的每一层在包装并传递异常的时候要过滤掉RuntimeException!
U4[7I v8{Uk^NgT 4。从责任这个角度看Error属于JVM需要负担的责任;RuntimeException是程序应该负担的责任;checked exception 是具体应用负担的责任 JAVA中文站社区门户SG#c,otZK9V&j
 5。无论如何我们都不希望或者确切的说是不应该将RuntimeException这样的异常暴露给客户的,因为他们没有解决这个问题的责任! JAVA中文站社区门户2U*Ro8XMH3[,z

你可能感兴趣的:(java,exception,null,c,框架,struts)