一、异常的层次框架
Error往往是硬件异常,Exception是程序异常,其中分为检查异常和非检查异常,检查异常如果不被处理,无法通过编译,但是非检查异常不被处理也可以通过编译,更多是代码的逻辑错误。
二、Throwable常用的方法
- String getMessage(): 返回异常发生时的简要描述
- String toString(): 返回异常发生时的详细信息
- String getLocalizedMessage(): 返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
- void printStackTrace(): 在控制台上打印 Throwable 对象封装的异常信息
三、异常的使用
对于检查性异常,有两种不同的处理方式:
- 使用 「try…catch…finally…」 语句块处理
- 在方法中使用 「throws/throw」 关键词将异常交给方法调用者去处理
使用throw或throws关键字抛出异常,多个异常用逗号分隔
3.1 try-catch-finally关键字
把try/catch 代码块放在异常可能发生的地方。
try {
...
} catch (IOException ioException) {
...
} catch (Exception exception) {
...
} finally {
...
}
try块:
- 如果执行完try且不发生异常,则接着去执行finally块中的代码和finally后面的代码(如果有的话)。
- 如果程序发生异常,则尝试去匹配对应的catch块。
catch块:
- 每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。
- catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的,则虚拟机将使用这个catch块来处理异常。
- 在catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问。
- 如果当前try块中发生的异常在后续的所有catch中都没捕获到,则先去执行finally,然后到这个方法的外部调用者中去匹配异常处理器。
- 如果try中没有发生异常,则所有的catch块将被忽略。
finally 块:
- finally块不是必须的,通常是可选的。
- 无论异常是否发生,异常是否匹配被处理,finally中的代码都会执行。
- 一个try至少要有一个catch块,否则, 至少要有1个finally块。但是finally不是用来处理异常的,finally不会捕获和处理异常,处理异常的只能是catch块。
- finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。
- finally块不管异常是否发生,只要对应的try执行了,则它一定也执行。只有一种方法让finally块不执行:「System.exit()」 。
注意:
(1)如果程序有return,则先执行完finally再执行return。
(2)catch的执行顺序是自上而下的,因此,应该先放子类的异常,再写父类的异常。
(3)资源要在finally中关闭
(4)不要在 finally 语句块中使用 return! 当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句不会被执行。
举例如下:
public class TestStream {
public static void main(String[] args) {
File f = new File("d:/test.txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 在finally 里关闭流
if (null != fis)
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
3.2 try-with-resource关键字
将资源定义在try里面,会自动释放资源。
举例如下:
public class TestStream {
public static void main(String[] args) {
File f = new File("d:/lol.txt");
//把流定义在try()里,try,catch或者finally结束的时候,会自动关闭
try (FileInputStream fis = new FileInputStream(f)) {
byte[] all = new byte[(int) f.length()];
fis.read(all);
for (byte b : all) {
System.out.println(b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
声明多个资源,使用分号隔开
try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
int b;
while ((b = bin.read()) != -1) {
bout.write(b);
}
}
catch (IOException e) {
e.printStackTrace();
}
在 try-with-resources 语句中,任何 catch 或 finally 块在声明的资源关闭后运行
补充
java异常的最佳实践:
https://blog.youkuaiyun.com/hejjunlin/article/details/124829929