这里写自定义目录标题
一、异常分类
在 Java 程序设计语言中, 异常对象都是派生于 Throwable 类的一个实例。
查看javaAPI,异常属于java.lang
首先我们来看一下java异常层次结构图
Exception 层次结构。 这个层次结构又分解为两个分支:一个分支派生于 RuntimeException ; 另一个分支包含其他异常。划分两个分支的规则是:由程序错误导致的异常属于 RuntimeException ; 而程序本身没有问题, 但由于像 I/O 错误这类问题导致的异常属于其他异常:
“ 如果出现 RuntimeException 异常, 那么就一定是你的问题” 是一条相当有道理的规则。
应该通过检测数组下标是否越界来避免 ArraylndexOutOfBoundsException 异常;应该通过在使用变量之前检测是否为 null 来杜绝 NullPointerException 异常的发生:
Java 语 言 规 范 将 派 生 于 Error 类 或 RuntimeException 类的所有异常称为非受查( unchecked ) 异常,所有其他的异常称为受查( checked) 异常。
二、对比
2.1 Error与Exception
Error 类层次结构描述了 Java 运行时系统的内部错误和资源耗尽错误。是程序无法处理的错误,它是由JVM产生和抛出的,,比如OutOfMemoryError、ThreadDeath等。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
Exception 是程序本身可以处理的异常,这种异常分两大类运行时异常和非运行时异常。程序中应当尽可能去处理这些异常。
2.2 受查异常和非受查异常如何规避
受查异常 要使用 try-catch 或者通过 throws 关键字抛出异常的形式处理掉
非受查异常 所有的都不需要使用者两种形式,只要在代码中规避就可
2.3 运行时异常和非运行时异常
运行时异常 都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
非运行时异常 是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
三、异常关键字
- try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
- catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
- finally – finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
- throw – 用于抛出异常。
- throws – 用在方法签名中,用于声明该方法可能抛出的异常。
四、try-catch-finally
4.1 异常处理步骤
4.2 try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗
finally代表一定会执行
例子 1
public static int getInt() {
int a = 10;
try {
System.out.println(a / 0);
a = 20;
} catch (ArithmeticException e) {
a = 30;
return a;
/*
* return a 在程序执行到这一步的时候,这里不是return a 而是 return 30;这个返回路径就形成了
* 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40
* 再次回到以前的路径,继续走return 30,形成返回路径之后,这里的a就不是a变量了,而是常量30
*/
} finally {
a = 40;
}
return a;
}
执行结果:30
例子 2
public static int getInt() {
int a = 10;
try {
System.out.println(a / 0);
a = 20;
} catch (ArithmeticException e) {
a = 30;
return a;
} finally {
a = 40;
//如果这样,就又重新形成了一条返回路径,由于只能通过1个return返回,所以这里直接返回40
return a;
}
执行结果:40