我爱电脑技术论坛's Archiver

麦迪 发表于 2008-4-19 01:21

JAVA编程中异常问题处理方式的区别和分析

一、内层方法抛出异常,外层方法捕捉并处理异常:
7k*y5y X-vBT Q2x:v
Do$XqI _s5Uv ^4J/gC9xVS e
public void methodA (){
p!rOO.NF:d%a.` MmKG(])a0q
try{
U k:t H.`2G 7z6g{%} @]
// 调用methodB
!T5SgXGf`6\)A#r'Qr
1r*Qm}4AD U methodB();
[{(^$KXO
VP%b2`WT#K } q1P0J'WJTs

sW/?0K2T5O catch(ExceptionType et){ ,KFcN:X/fg7}Wg
I]aLS X;L
// 相应处理措施 l&c.Tz3^ RFZ0y?
k/EIe Cn-t.b#KA
}
g1SIT6V4t.^
y Px$W(WJg }
BU1AL"u"?J_j
)]\;B.R+U hwe
`[;_#[P public void methodB throws ExceptionType{ gU1u|i0H*Nd'^ ?
[!f'N-~k2eF#d
if (condition is true)
R9bb9|0o0sUAS-lv6Y D|L [ Y
{
m]&Q{4pc^;U
u7Z%?prs:l // 相应处理措施
ec@,Q6I ums#V$X!oA4L7w
}
~-W$c4W6v)Ss @
nR\5j)b.IT ?;{t LT else X^;n9E%TP

;X u sBL$W4{qx { b+b9G5L:OloQ

i1o+oDL{ throw new ExceptionType(argument);
.Kg id0F_
0I.yu;?:w }
7wQIj];{@+Ejc
I-gK:~j/^%S { } *`"R r4VF7X f

/]*{*nA^.lo
9b;gM0Qe]&n 在这个例子中,方法B的头部中声明了该方法会抛出一个类型为ExceptionType的异常,在方法体中使用throw子句抛出了一个异常,那么该异常被谁捕捉到呢,答案是方法A。因为异常抛出后,JVM会顺着该方法的调用栈一层一层的往上找。因为方法A中有一个catch(ExceptionType et),所以被抛出的异常会被捕捉到并处理。
F&xB VE&i W#Y)h f-Ei`d9IIwLS

j ma"x'OW a p M A(x~
二、方法中自己捕捉,处理异常:
cIk9`%T'l@t3?
:x.IG$@qu} py/MD3X+hx_
public methodA() {
|ldY8Wyf)]-zI 3gu?Rb.g
try
-Q2P)I+?G-bvt
tkmB1L r!ej V { ziMq_5Y]
`I!|#k GzH
// 可能产生异常的语句
|uZ(d)A*s *w o J5mBt#X/Xg
} S1S(ZHn-X
D6b"v~}
catch (ExceptionType et)
.i?kc9Df J/K7p8jsU}As
{
PsO O N+R)D.bKo
;b5@(TX lTf&m // 相应的处理
Z/f$`(sq+Y
/\ BqO gn}{-G }
0m:}m;TZ@2r@aY
X T-u w;W_e ~*JY }
*Q1d,S\9Nf4C u4a+aD^`,mQ
在这个例子中,方法A使用了try-catch语句块,那么意味着在方法中所产生的ExceptionType类型的异常都会被捕捉到并在方法内处理。 oI't~ a^G@7@)z

8[ ^ k:o%_z-SN 8|0O'\|j4o G

'Uo{#Ci8Fo,D4z 三、内层方法抛出一个异常,但本身又有try-catch 3I~$V r$j

q6v4l0N$~YUav Y
2wDm#]PX B:qz Yy public methodB() throws ExceptionType{
*z_|fl
:_t5q&Ua:s @
g5M2AnZynO^:m try 8| U!cP6Zv h@:L
t'l0ekU3N+J^4l
{
(@T iL3I l'kL
0|f:?-sT2X // 可能产生异常的语句 b rarUgk d3~ ~9KK

} Kb{W%i6vt1e } 7F$_Uh9N4J

%|j9}8j:D$k,RO#BLJX catch (AnotherExceptionType aet)
h(i k:N3Nf 'm2s,e Yq M1_.?
{ %NV!nG l/YKC
_m![9V_1T6x
// 相应处理措施
i6[tT,I*p
'W"S@ee%R } 2Fb@'y2?)sHC,[

,M5n?7i9H } C VC2[F&^V
3~+J.\qiwr6^J
在这个例子中有两种异常处理情况,抛出异常和捕捉异常,如果在try语句块中产生ExceptionType类型的异常的话,会被抛出。如果产生AnotherExceptionType类型的话,则不会被抛出,因为在方法B的头部中并没有声明会抛出该异常。
u#Y-A3]"l&c$D rb C3nRH9\j#e
6f/Z/h] ^}/\7`l

7uR7r&@ g+B^ 四、内层方法抛出一个异常,但本身有try-finally
U+zy\&g[
khB`:w$N*I6T4{R5k
T6a~7R2F/B2V^E public methodB() throws ExceptionType{ (vf(m5i;t
`!I\0{4{d!q8C

}lr&py _O try
bBIfVoY
S+|t!U7F _F { gcK/fIu

,|$p+YU*l$W&e // 可能产生异常的语句
#N"LeE4|.l Ksy4FU \ LD:q
}
hL:tD l!r
l EO&N*U5YhyO+o0R finally
[!m dU'A0uue|A+v
{;R1`!M2_HE&u { A)F d }0v@Q
4ZNioR
// 一定要执行的语句
Qd*Ap{ 8vc0OsL+l
}
+Da O;PU@ *Z#Co b F
}
#|k@o Uo4a$_7m
`7f"i*Jz/p gHn 这个例子与上一个例子很像,不同的是没有catch,但增加了finally。它的意思如果方法B中try语句块中如果产生了异常,则抛出由外层方法处理。然后方法B继续执行finally中的语句 \'Q2S7Gn*];L1u

X!l|P9TKS%y 9E7v8C+tyOr9I%V
:[L6y+V[
下面列举三种错误的异常处理方法:
)_AIM7|7}"Z7aA
~$@:rTK;q5_
nPd@&DZFf 一、内层方法抛出一个异常,但本身有捕捉这个异常 Z-jYJ P9\lU
kEfk `
)_FyQ#G[f
public methodB() throws ExceptionType{
Y]9t%lSS#l
y.yDK$~*p$@EO @/zY!LO(Kq
try 9t`]L9VBy3C q

'W'B:lLC2e2C} S {
:@A[x SC xZ8~\GL]W(~
// 可能产生异常的语句
X!Xm"@O2x(c
)vyI'vQQ;\ } )l&?0lD#q-Yt6`

+ml#sG#cr6EZ catch (ExceptionType et) T4CP8Jr{ }X

yF+^.nU { +h j]o,no;M
oOlBwe,rh
// 相应处理措施
hYBB0a/[xD
!pY9~?s:J Q,] }
U$s{R1|)pV^ ] 3z,Zj%s j:h7^%V.G
}
:?(p\_fj/_
)juYT)N#G T 在这个例子中,方法B在头部声明了会抛出一个类型为ExceptionType的异常,但在紧接下来的方法体又用了catch(ExceptionType et),如果产生了异常的话,会有什么结果呢?方法B抛出的异常马上被自身的catch捕捉到,所以方法头部的throws实际是没有作用的。外层方法是接收不到方法B抛出的异常对象的。
`Egi\v^s O2Yj6P.f'x-`m
0c9p4]O{%J^6] KH

@vQl5^lJ/w:d!x cn 二、在try中使用了return,在fianlly中又使用了return f,w#n OG)h-Ge
:z@'CFN}*Uf

5]-z*GQ#VR public methodB() {
bhX1h%CCq%N?8~Fpq b}!a c.YT6s}R"R
j r:c,Y8Fz*i
try
8m0a:K|:r6GX:E'p r5_{|NXgh
{
{4|4D`$I@
c9b2Fg0F // 可能产生异常的语句
%Li N4^5E5Lx !QZv_EZp3m
return SOMEVALUE;
7R,^"uF s{t3Z
[P s$RQ!?#G{ }
M*f({\1HB.nf
!r1[ aQQgv9aZ catch ()
'wW!`1Y^5W:r
&[T}LfvM { E*`xk)bmM6QL;r

hR v*mB }%R&Y }
@3ap*Y|f'|z$H"q
.TN'R;@5IM finally 4F6zS{ cp.g
G8{-ul1h[1k/i"a Rv
{ 9V O"u$qyx X8Pe

kv^$hF[ ^`J return SOMEVALUE_2; ~W%\2VQ5x It)Y

+|M q w$uoD }
Iu!Zzwa3H5G
h.E,XX'@%S-DVS
W*C A7d ?&k k&S3`(x }
k8\qG.SMF*ob6y k-K
(J&H/I/c[8@.KS9} }E@ 在这个例证中,我们可以看到在try中返回了SOMEVALUE,那么程序执行到这里是否就结束了呢,其实不是的,因为finally中的语句是肯定会被执行到的,所以最后返回的是SOMEVALUE_2;那么意味者即使程序没有抛出异常,最后也得不到正确的结果。
e {!w-X4a e&u@ O+xlc`d
)Gn)G0A+QV;R

nXh6z h 三、把catch(Exception e)放在所有catch块的最前面
+g:w y\Egc5si;\{
z Qw?p!J.B,L public methodB(){ Rh8\6F,B(s?.QH
D^ u.gR&C
try %W R2[S1sm/j h$[9R
d$`c"v{!Lw
{ J2|7Qdl4|'O
h1G0cQ CZw#ny
Lf@E{(V4h|#t
}
v'PfRon4f K-g\\"N
catch (Exception e) &@5rj*PE%Tu
?'u8h:P7kb
{ X F6t/u0~j|^;Wim
G%KE Z pnf(r`*I
... p~1hnH/kZ
b tNS L{.^!ol
}
_ D-I,{$z!q QE
.z b ]NZw"u4G&j"g\ catch (SubException se)
9l W8t;@5ws3g !Pd+| Vv`0p O)a
{
e3Blv w:W8r}w:m2lB )w|7|\ @
... 5HG:kn,rNR

i(hI.PI|-g } ,K1o@w:v#@0cr
+?9x+nF{8u$f
1]G(p`*t.Qc
}
X$Eb$x MW 7h0Fv{4e4DJY;{7}
在这个例子中,catch(Exception e)被放在所有catch语句块的最前面,因为Exception所有Exception类型的父类,所以意味着所有在try中产生的异常都会被捕捉到。后面其他的catch都是没有用的,所以一定要把catch(Exception e)放在最后面,如果前面所有的异常类型都不符合,至少保证还有一个可以处理它。 &U7E$BCO%n
0tv"Q0sC8a$E

zx\G2a#L+U W9J B 总结: 2D0y&Bw9}0af%t+Z

2S4Y(LoKg7Y A.如果能够找到一个有意义的方法来捕获异常,就立即引入这个方法
sVn RT 4BSsf L0q-?7K;s w[ a
B.否则就应该考虑做某些处理后传递或者再次抛出异常,也可以把异常转换为另一种形式,然后抛出一个新的异常 W p@1h/C9Q!o6b

+h,i"X%H&tz a-Xm&z C.另一个方法是,可以完全忽略这个异常,而把它加到方法的头部的throws语句中,由调用这个方法的方法来处理它
.V\J&|9jS&VQ3I s:g2V+H__7lSU
D.通过捕获一个公共的异常超类,可以在一个块里面捕获多个异常,但不能够用一个空的catch语句 块来完全制止一个异常。

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.