Java基础知识——通过异常处理错误

本文最后更新于:2023-03-13, 23:48:49

1、基本异常

抛出异常后,有几件事情会发生。首先,同Java中其他对象的创建一样,将使用new在堆上创建异常对象。然后,当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序,这个恰当的地方就是异常处理程序。

所有标准异常类都有两个构造器,一个是默认构造器,另一个是接受字符串作为参数的构造器。

2、捕获异常

如果在方法内部抛出了异常(或者在方法内部调用的其他方法抛出了异常),这个方法将在抛出异常的过程中结束。要是不希望方法就此结束,可以在方法内设置一个特殊的块(即try{…})来捕获异常。

当然,抛出的异常必须在某处得到处理,即异常处理程序,针对每个要捕获的异常,得准备相应的处理程序。异常处理程序紧跟在try块之后,以关键字catch表示。

1
2
3
4
5
6
7
try{
//code that might generate exception
}catch(Type1 id1){
//Handle exception of Type1
}catch(Type2 id2){
//Handle exception of Type2
}

每个catch子句看起来就像是接收一个且仅接收一个特殊类型的参数的方法。可以在处理程序的内部使用标识符(id1,id2等),这与方法参数的使用很相似。有时可能用不到标识符,因为异常的类型已经给了你足够的信息来对异常进行处理但标识符并不可省略。

3、创建自定义异常

要自己定义异常类,必须从已有的异常类继承,最好是选择意思相近的异常类继承(不过这样的异常类并不容易找)。建立新的异常类型最简单的方法就是让编译器为你产生默认构造器。

4、异常说明

Java鼓励人们把方法可能会抛出的异常告知使用此方法的客户端程序员。这就是异常说明,它属于方法的一部分,紧跟在形参之后,例:

1
void f() throws TooBig, TooSmall, DivZero{ //... }

如果在方法的代码里产生(new)了异常却没有处理,编译器会发现这个问题并提醒你:要么处理这个异常,要么在异常说明中表明此方法将产生异常。

5、捕获所有异常

可以只写一个异常处理程序来捕获所有类型的异常,通过捕获异常类型的父类Exception,就可以做到这一点。

1
2
3
catch(Exception e){
//...
}

这将捕获所有异常,所以最好把它放在处理程序列表的末尾,以防它抢在其他处理程序之前先把异常捕获了。

6、Java标准异常

Throwable这个 Java类被用来表示任何可以作为异常被抛出的类。Throwable对象可分为两种类型(即继承Throwable的类型):Error用来表示编译时和系统错误(除特殊情况外,一般不需要你关心);Exception是可以被抛出的基本类型。

特例:RuntimeException

1
2
if(t == null)
throw new NullPointerException();

在上面这个例子中,如果必须对传递给方法的每个引用都检查其是否为null,这听起来着实吓人。幸运的是,你不必亲自来做,它属于Java的标准运行时检测的一部分。如果对null引用进行调用,Java会自动抛出NullPointerException异常,所以上述代码是多余的。

属于运行时异常类型很多,这些异常都是从RuntimeException类继承而来。并且,也不需要在异常说明中声明方法将抛出RuntimeException类型的异常(或者它的子类异常),它们被称为不受检查异常。这种异常属于错误,将被自动捕获。

7、使用finally进行清理

对于一些代码,可能希望无论try块中的异常是否抛出,它们都能得到执行。为了达到这个效果,可以在异常处理程序后面加上finally子句。完整的异常处理程序看起来像这样:

1
2
3
4
5
6
7
8
9
try{
//might throw some exception
}catch(A a){
//handler for A
}catch(B b){
//handler for B
}finally{
//activities that happen every time
}

finally子句总能被执行,即使try块里有return语句。

8、异常匹配

抛出异常的时候,异常处理系统会按照代码的书写顺序找出最近的处理程序。找到匹配的处理程序之后,它就认为异常将得到处理,然后就不再继续查找。

查找的时候并不要求抛出的异常同处理程序所声明的异常完全匹配。子类的对象也可以匹配其父类的处理程序。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!