java 异常处理

java 异常的简单整理。

本文参考自Java异常处理和设计

异常

  异常的英文单词是 exception,字面翻译就是“意外、例外”的意思,也就是非正常情况。事实上,异常本质上是程序上的错误,包括程序逻辑错误和系统错误。比如使用空的引用、数组下标越界、内存溢出错误等,这些都是意外的情况,背离我们程序本身的意图。错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间的错误,在编译期间出现的错误有编译器帮助我们一起修正,然而运行期间的错误便不是编译器力所能及了,并且运行期间的错误往往是难以预料的。假若程序在运行期间出现了错误,如果置之不理,程序便会终止或直接导致系统崩溃,显然这不是我们希望看到的结果。因此,如何对运行期间出现的错误进行处理和补救呢?Java提供了异常机制来进行处理,通过异常机制来处理程序运行期间出现的错误。通过异常机制,我们可以更好地提升程序的健壮性。

​ 在 java 中,异常被当做对象来处理。如上图所示,异常根类为 java.lang.Throwable 类,java 中有很多不同种类的异常,根据这些异常的不同分为两大类,Error 和Exception。

Error

​ 是我们经常见到的一些异常情况,比如NullPointerException、IndexOutOfBoundsException,这些异常是我们可以处理的异常。

Exception

​ Exception类的异常包括checked exception和unchecked exception。

checked exception

​ 检查异常,也称非运行时异常(运行时异常以外的异常就是非运行时异常),java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。

unchecked exception

​ 非检查异常,也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。

​ 正如上面图片所显示的一样,所有的异常类父类都是 Throwable 类,其他结构同理。

处理异常

捕获异常

​ 在处理异常之前,需要先捕获到异常,然后再对异常情况进行处理,异常的捕获使用关键字 try 和 catch 。格式如下:

1
2
3
4
5
6
7
try {
File file = new File("d:/a.txt");
if(!file.exists())
file.createNewFile();
} catch (IOException e) {
// TODO: handle exception
}

​ try 部分为可能抛出异常的代码部分,当抛出异常后,catch 便会去捕捉异常。如果被 catch 捕捉到,那么 catch 就会去处理这些异常。

抛出异常

​ 捕获异常指开发人员自己需要去处理这些异常。假如说开发者不需要捕获这些异常,将捕获异常的处理任务留给调用者,那么就需要抛出异常。

​ 抛出异常有两种方式,第一种是在声明方法时抛出声明,告知此方法可能会产生异常;另一种方法是是在代码中手动抛出异常。格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Main {
public static void main(String[] args) {
try {
createFile();
} catch (Exception e) {
// TODO: handle exception
}
}
// 利用关键字 throws 声明抛出异常,告知调用者可能会抛出 IOException 异常。
public static void createFile() throws IOException{
File file = new File("d:/a.txt");
if(!file.exists())
file.createNewFile();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
public static void main(String[] args) {
try {
int[] data = new int[]{1,2,3};
System.out.println(getDataByIndex(-1,data));
} catch (Exception e) {
System.out.println(e.getMessage());
}

}
// 利用 throw 关键字手动抛出异常,
public static int getDataByIndex(int index,int[] data) {
if(index<0||index>=data.length)
throw new ArrayIndexOutOfBoundsException("数组下标越界");
return data[index];
}
}

关键字

try、catch、finally

try

​ try 用来包围可能抛出异常的逻辑代码,在使用时必须需要配合 catch、finally 关键字使用。

catch

​ catch 用来捕获 try 抛出的异常,根据异常的种类选择适当的 catch 块去进行处理。由于 catch 是按照代码顺序进行执行,因此规定子类异常处理必须在父类异常之前,否则子类异常 catch 块将永远不会执行(向上转型)。

finally

​ finally 不管在任何情况下都会执行,因此常用于释放资源操作。

代码格式

​ java 支持以下几种格式,三种块的执行顺序也如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
try {

} catch { // 可多个catch

}

/***************/

try {

} finally { // 只能有一个finally

}

/***************/

try {

} catch { // 可多个 catch

} finally { // 只能有一个 finally

}

​ 这里需要注意,如果 catch 块有 return 值,而 finally 也有 return 值,那么 finally 将会覆盖 catch 的 return 值,因为 finally 总是最后执行的。因此在非必要情况下,不允许在 finally 中使用 return 。

throw、throws

​ 如抛出异常章节所示,throws 用在方法的声明中,表示该方法可能会抛出异常。throws 后面可跟多种异常。

​ throw 用在方法体中,当代码执行过程中遇到异常情况时,将异常情况包装成异常对象,然后 throw 出去。

感谢您的支持
-------------本文结束感谢您的阅读-------------