Java语言基础:异常机制
2011年03月29日 19:38 发布者:1770309616
345661. 抛出异常•通过throw new ThrowableClass语法可以抛出一个异常,其中ThrowableClass是一个从Throwable继承的类,或者是Throwable类本身,先看下面的
view plaincopy to clipboardprint?
01.public void proc(){
02. // Exception是Throwable的继承类,代表最基本的异常
03. throw new Exception("hello");
04.}
public void proc(){
// Exception是Throwable的继承类,代表最基本的异常
throw new Exception("hello");
}
•上面的代码会导致编译错误,对于有抛出异常的方法,编译器强制要求:要么在方法上声明要抛出的异常(称为异常说明),要么在方法中用try块捕获这个异常。
view plaincopy to clipboardprint?
01.// 用异常说明,说明该方法要抛出的异常
02.public void proc() throws Exception{
03. throw new Exception("hello");
04.}
05.
06.// 用try块捕获该异常
07.public void proc(){
08. try {
09. throw new Exception("hello");
10. } catch (Exception e) {
11. e.printStackTrace();
12. }
13.}
// 用异常说明,说明该方法要抛出的异常
public void proc() throws Exception{
throw new Exception("hello");
}
// 用try块捕获该异常
public void proc(){
try {
throw new Exception("hello");
} catch (Exception e) {
e.printStackTrace();
}
} 异常说明可以是方法抛出的异常类本身,也可以是异常类的基类,比如throws后面可以是throwable。•上面说到对于有抛出异常的方法,必须带有方法声明,这并不准确,当抛出的异常类是RuntimeException或其继承类时,不需要异常说明:
view plaincopy to clipboardprint?
01.// RuntimeException或其继承类不需要异常声明
02.public void proc(){
03. throw new RuntimeException("hello");
04.}
// RuntimeException或其继承类不需要异常声明
public void proc(){
throw new RuntimeException("hello");
} •一个方法即使内部没有抛出异常,也仍然可以带有异常说明:
view plaincopy to clipboardprint?
01.public void proc2() throws NullPointerException, FileNotFoundException {
02.}
public void proc2() throws NullPointerException, FileNotFoundException {
} •一个方法若带有异常说明,则调用它的其他方法也要带有异常说明,或者要捕获可能抛出的异常:
view plaincopy to clipboardprint?
01.class A {
02. public void proc() throws Exception {
03. throw new Exception("hello");
04. }
05. // 异常声明
06. public void proc1() throws Exception {
07. proc();
08. }
09. // 异常声明,声明中的类可以是基类
10. public void proc2() throws Throwable {
11. proc();
12. }
13. // 直接捕获异常
14. public void proc3() {
15. try {
16. proc();
17. } catch (Exception e) {
18. e.printStackTrace();
19. }
20. }
21.}
class A {
public void proc() throws Exception {
throw new Exception("hello");
}
// 异常声明
public void proc1() throws Exception {
proc();
}
// 异常声明,声明中的类可以是基类
public void proc2() throws Throwable {
proc();
}
// 直接捕获异常
public void proc3() {
try {
proc();
} catch (Exception e) {
e.printStackTrace();
}
}
} •可以基于Exception现实自己的异常类:
view plaincopy to clipboardprint?
01.class MyException1 extends Exception {
02.}
03.class MyException2 extends Exception {
04.}
05.class A {
06. public void proc() throws MyException1, MyException2{
07. }
08.}
class MyException1 extends Exception {
}
class MyException2 extends Exception {
}
class A {
public void proc() throws MyException1, MyException2{
}
}
2. 捕获异常和结束清理•用try{}块包围住可能引发异常的代码,后面紧跟着异常处理器(即catch(...){}块);catch块可以有多个,()中声明要捕获的异常类。当try块抛出一个异常时,执行代码将跳到catch块去,并从第一个catch块开始匹配,直到找到符合的catch块。请看下面的代码说明:
view plaincopy to clipboardprint?
01.class MyException1 extends Exception {
02.}
03.class MyException2 extends Exception {
04.}
05.class MyException3 extends Exception {
06.}
07.class A {
08. public void proc() throws Exception{
09. try{
10. // 仅仅为了演示用
11. Random random = new Random();
12. int i = random.nextInt(3);
13. if (i == 0)
14. throw new MyException1();
15. else if (i == 1)
16. throw new MyException2();
17. else if (i == 2)
18. throw new MyException3();
19. }
20. catch(MyException1 e){
21. // 当抛出MyException1时会跳到这里来。
22. e.printStackTrace();
23. }
24. catch(MyException2 e){
25. // 当抛出MyException2时会跳到这里来。
26. e.printStackTrace();
27. }
28. catch (Exception e) {
29. // 当抛出MyException3时,由于上面没有匹配的处理器,
30. // 并且Exception是MyException3的基类,所以会跳到这里来。
31. e.printStackTrace();
32. // 可以重新抛出异常,系统将寻找更外层的异常处理器
33. throw e;
34. }
35. }
36.}
37.
38.public class Main {
39. public static void main(String[] args) {
40. A a = new A();
41. try {
42. a.proc();
43. } catch (Exception e) {
44. e.printStackTrace();
45. }
46. }
47.}
class MyException1 extends Exception {
}
class MyException2 extends Exception {
}
class MyException3 extends Exception {
}
class A {
public void proc() throws Exception{
try{
// 仅仅为了演示用
Random random = new Random();
int i = random.nextInt(3);
if (i == 0)
throw new MyException1();
else if (i == 1)
throw new MyException2();
else if (i == 2)
throw new MyException3();
}
catch(MyException1 e){
// 当抛出MyException1时会跳到这里来。
e.printStackTrace();
}
catch(MyException2 e){
// 当抛出MyException2时会跳到这里来。
e.printStackTrace();
}
catch (Exception e) {
// 当抛出MyException3时,由于上面没有匹配的处理器,
// 并且Exception是MyException3的基类,所以会跳到这里来。
e.printStackTrace();
// 可以重新抛出异常,系统将寻找更外层的异常处理器
throw e;
}
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
try {
a.proc();
} catch (Exception e) {
e.printStackTrace();
}
}
} •在异常处理器后面加上finally子句,无论异常是否发生,finally子句一定会被调用到,finally子句常被用于清理垃圾回收之外的资源,比如打开的文件,网络链接等:
view plaincopy to clipboardprint?
01.class MyException1 extends Exception {
02.}
03.
04.class A {
05. public void proc(){
06. try{
07. throw new MyException1();
08. }
09. catch(MyException1 e){
10. e.printStackTrace();
11. }
12. finally {
13. System.out.println("Hello");
14. }
15. }
16.}
17.
18.public class Main {
19. public static void main(String[] args) {
20. A a = new A();
21. a.proc();
22. }
23.}
24.最后的输出是:
25.MyException1
26. at A.proc(Main.java:12)
27. at Main.main(Main.java:27)
28.Hello
class MyException1 extends Exception {
}
class A {
public void proc(){
try{
throw new MyException1();
}
catch(MyException1 e){
e.printStackTrace();
}
finally {
System.out.println("Hello");
}
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.proc();
}
}
最后的输出是:
MyException1
at A.proc(Main.java:12)
at Main.main(Main.java:27)
Hello
3. 异常的限制:对于继承类,它如果所覆盖的方法有异常说明,则所列出的异常类,必须是基类该方法所列出的异常类的子集,先看一个例子:view plaincopy to clipboardprint?
01.class MyException1 extends Exception {
02.}
03.class A {
04. public void proc(){
05. }
06.}
07.class B extends A {
08. // 编译错误:因为A.proc没有异常说明,所以子类也不能有异常说明
09. // 解决的方法是为A.proc加上异常说明:throws MyException1
10. // 或者在throw new MyException1();加上try块并去掉异常说明
11. public void proc() throws MyException1 {
12. throw new MyException1();
13. }
14.}
class MyException1 extends Exception {
}
class A {
public void proc(){
}
}
class B extends A {
// 编译错误:因为A.proc没有异常说明,所以子类也不能有异常说明
// 解决的方法是为A.proc加上异常说明:throws MyException1
// 或者在throw new MyException1();加上try块并去掉异常说明
public void proc() throws MyException1 {
throw new MyException1();
}
}
再看一下例子:view plaincopy to clipboardprint?
01.class MyException1 extends Exception {
02.}
03.class MyException2 extends Exception {
04.}
05.class A {
06. public void proc() throws MyException1 {
07. }
08.}
09.class B extends A {
10. // 错误:因为A.proc只声明了MyException1异常
11. public void proc() throws MyException2 {
12. }
13.}
class MyException1 extends Exception {
}
class MyException2 extends Exception {
}
class A {
public void proc() throws MyException1 {
}
}
class B extends A {
// 错误:因为A.proc只声明了MyException1异常
public void proc() throws MyException2 {
}
} 构造器是一个例外,继承类可以声明更多的异常类,但必须加上基类所声明的异常类:view plaincopy to clipboardprint?
01.class MyException1 extends Exception {
02.}
03.class MyException2 extends Exception {
04.}
05.class A {
06. A() throws MyException1 {
07.
08. }
09. public void proc() throws MyException1 {
10. }
11.}
12.class B extends A {
13. B() throws MyException1, MyException2 {
14. }
15.}
class MyException1 extends Exception {
}
class MyException2 extends Exception {
}
class A {
A() throws MyException1 {
}
public void proc() throws MyException1 {
}
}
class B extends A {
B() throws MyException1, MyException2 {
}
}