1. Java 异常类层次结构图
在 Java 中,所有的异常都有⼀个共同的祖先java.lang
包中的Throwable
类。Throwable
类有两个重要的⼦类Exception
(异常)和Error
(错误)。Exception
能被程序本身处理(try-catch
),Error
是⽆法处理的(只能尽量避免)。
Exception
和Error
⼆者都是 Java 异常处理的重要⼦类,各⾃都包含⼤量⼦类。
Exception
:程序本身可以处理的异常,可以通过catch
来进⾏捕获。Exception
⼜可以分为受检查异常(必须处理)和不受检查异常(可以不处理)。Error
:Error
属于程序⽆法处理的错误,我们没办法通过catch
来进⾏捕获。例如,Java 虚拟机运⾏错误(VirtualMachineError
)、虚拟机内存不够错误(OutOfMemoryError
)、类定义错误(NoClassDefFoundError
)等。这些异常发⽣时,Java虚拟机(JVM)⼀般会选择线程终⽌。
受检查异常
Java 代码在编译过程中,如果受检查异常没有被catch/throw
处理的话,就没办法通过编译。⽐如下⾯这段 IO 操作的代码。
class Example {
public static void main(String args[]) throws IOException {
FileInputStream fis = null;
fis = new FileInputStream("B:/myfile.txt");
int k;
while ((k = fis.read()) != -1) {
System.out.print((char) k);
}
fis.close();
}
}
除了RuntimeException
及其⼦类以外,其他的Exception
类及其⼦类都属于受检查异常。常⻅的受检查异常有:IO 相关的异常、ClassNotFoundException
、SQLException
···
不受检查异常
Java 代码在编译过程中,我们即使不处理不受检查异常也可以正常通过编译。RuntimeException
及其⼦类都统称为⾮受检查异常,例如:NullPointExecrption
、NumberFormatException
(字符串转换为数字)、ArrayIndexOutOfBoundsException
(数组越界)、ClassCastException
(类型转换错误)、ArithmeticException
(算术错误)等。
2. Throwable 类常⽤⽅法
public string getMessage()
: 返回异常发⽣时的简要描述public string toString()
: 返回异常发⽣时的详细信息public string getLocalizedMessage()
: 返回异常对象的本地化信息。使⽤Throwable
的⼦类覆盖这个⽅法,可以⽣成本地化信息。如果⼦类没有覆盖该⽅法,则该⽅法返回的信息与getMessage()
返回的结果相同public void printStackTrace()
: 在控制台上打印Throwable
对象封装的异常信息
3. 异常处理总结
try
块:⽤于捕获异常。其后可接零个或多个catch
块,如果没有catch
块,则必须跟⼀个finally
块。
catch
块:⽤于处理try
捕获到的异常。
finally
块:⽆论是否捕获或处理异常,finally
块⾥的语句都会被执⾏。当在try
块或catch
块中遇到return
语句时,finally
语句块将在⽅法返回之前被执⾏。
在以下 3 种特殊情况下,finally
块不会被执⾏:
- 在
try
或finally
块中⽤了System.exit(int)
退出程序。但是,如果System.exit(int)
在异常语句之后,finally
还是会被执⾏ - 程序所在的线程死亡。
- 关闭 CPU。
注意:当try
语句和finally
语句中都有return
语句时,在⽅法返回之前,finally
语句的内容将被执⾏,并且finally
语句的返回值将会覆盖原始的返回值。如下:
public static int f(int value) {
try {
return value * value;
} finally {
if (value == 2) {
return 0;
}
}
}
如果调⽤f(2)
,返回值将是 0,因为finally
语句的返回值覆盖了try
语句块的返回值。
留言