Mais conteúdo relacionado
Semelhante a 11, exceptions (20)
11, exceptions
- 3. 概述
• 在程序的运行过程中可能由于各种原因导
致异常情况的发生, 比如文件访问权限不足/
数据库连接不可用等, 当这些异常情况发生
时应该决定是否进行捕捉以及如何处理, 这
个过程就称之为异常处理;
• 异常处理对于编写健壮代码十分重要, 同时
对于应用的可用性也很有帮助;为此java提供
了一套完整的异常处理框架.
- 4. 异常分类
• Java中的异常类都继承自java.lang.Throwable类,
该类有两个直接子类java.lang.Exception和
java.lang.Error; Java中的异常处理是指Exception
的处理, 对于程序抛出的错误(Error)是不应该在
程序中被处理的;
• Java中的异常(Exception)可以分为两类: 被捕捉
异常(checked exception)和不被捕捉异常, 后者
又称为运行时异常(RuntimeException), 前者在
方法中必须被捕捉或者继续向上抛出, 对于运
行时异常则可以不需要捕捉(也可以捕捉); 如图:
- 5. 异常分类
被捕捉异常
Exception
运行时异常
InterruptedE RuntimeEx
IOException
xception ception
ClassCastEx IllegalState
ception Exception
- 6. 方法异常声明
• 如果在一个方法中有可能会抛出异常, 那么
有两种选择, 一是在方法中捕获并处理该异
常, 二是在定义方法时使用throws关键字声
明抛出指定的异常; 比如:
void readFile(String fileName) throws IOException;
可以声明方法抛出多个异常使用逗号分隔, 比如:
void executeScript(String fileName) throws IOException,
SQLException;
- 7. 捕获异常
try...catch...
• 如果在方法中调用了抛出被捕捉异常的方, 法, 那么可以选择在方法中捕捉该
异常, 使用如下语法:
try {
// 抛出异常的代码
} catch(SomeException ex) {
// 处理该异常
}
其中catch中可以指定为具体的异常类型, 或者相应的父类型, 使用后者将
会捕捉该类型以及它所有子类的异常. 比如: 指定catch(Exception ex)那么
将会捕获Exception, IOException, RuntimeException以及所有其它的子异常
类型;
• 可以有多个catch分别指定不同的异常类型, 比如:
try {
...
} catch(IOException ex) {...}
catch(SQLException ex) {...}
需要注意的是在这种情况下前一个catch捕获的异常不能是后面catch捕获
异常的父类, 否则后面的catch块永远不会执行, 比如:
try {
...
} catch(Exception ex) {...}
catch(SQLException ex) {...// 不会被执行}
- 9. 异常堆栈
• 在捕捉异常之后, 可以使用方法printStackTrace打印异常堆
栈信息, 比如:
try {
...
} catch(Exception ex) {
ex.printStackTrace();
}
• 一个简单的异常堆栈:
demo.SimpleException: Throw SimpleException from f()
at demo.InheritingExceptions.f(Demo1.java:29)
at demo.Demo1.main(Demo1.java:10)
第一行显示的是异常类型和异常消息, 之后各行显示
的是方法调用堆栈, 由里到外; 可以看到异常是从
InheritingException.f方法中抛出的, 在main方法里面调
用了此方法.
• 将异常堆栈转换为字符串, 可以使用如下方法:
java.io.StringWriter writer = new java.io.StringWriter();
ex.printStackTrace(new java.io.PrintWriter(writer));
writer.toString(); // 返回异常堆栈字符串
- 10. 异常消息
• 在抛出异常时, 可以为该异常指定相关的信息, 这样
有助于代码的诊断; 比如:
throw new SomeException(“some message”);
前提是在SomeException类的定义中提供了相
应的构造器; 比如:
class SomeException extends Exception {
SomeException(String s) {
super(s); // 初始化消息
}
}
• 示例: demo/Demo2.java
- 11. 异常和日志
• 可以使用java.util.logging包下面的工具类记录相关的异
常信息, 示例:
import java.util.logging.*;
class SomeClass {
Logger logger = Logger.getLogger(“SomeClass”); // 返回Logger
对象
void f() {
try {
......
} catch(Exception ex) {
StringWriter trace = new StringWriter();
printStackTrace(new PrintWriter(trace));
logger.severe(trace.toString()); // 记录异常日志信息
}
• 示例: demo/Demo3.java
- 12. java.lang.Throwable
• 由于所有的异常类都继承自Throwable, 这里介绍一
下Throwable常用的方法:
1, String getMessage();
返回异常消息字符串
2, String getLocalizedMessage();
返回异常消息本地字符串
3, String toString();
将对象转换为一个字符串
4, void printStackTrace();
打印异常堆栈到标准错误(System.err)
5, void printStackTrace(PrintStream)
void printStackTrace(java.io.PrintWriter)
打印异常堆栈到指定的输出流
• 示例: demo/Demo4.java
- 13. java.lang.Exception
• Exception继承自Throwable类, 需要注意的是该类的构造方法:
1, Exception()
默认构造函数, 不指定异常消息或者子异常;
2, Exception(String msg)
字符串参数指定该异常的消息, 在异常堆栈中可以看到该消息, 比如下面
冒号后面部分就是异常消息:
demo.SimpleException: Throw SimpleException from f()
3, Exception(String msg, Throwable cause)
指定异常消息 和 导致当前异常的子异常. 示例”Caused by”部
分包
含的是子异常的堆栈信息:
Exception in thread "main" demo.Exception1: Exception1
......
Caused by: demo.Exception2: Exception2
......
4, Exception(Throwable cause)
仅指定子异常
- 14. 重新抛出异常
rethrow exception
• 在捕捉一个异常之后, 出于某些原因需要重新抛出该异常:
1, 记录该异常(logging), 然后重新抛出; 比如:
try {
...
} catch(Exception ex) {
... // 记录异常日志
throw ex; //重新抛出异常
}
2, 将该异常包装称自定义的异常, 并重新抛出. 典型的情况是使用
RuntimeException包装被捕捉异常:
try {
...
} catch(Exception ex) {
throw new MyException(ex); // 抛出自定义异常
}
• 示例: demo/Demo5.java
- 15. 运行时异常
RuntimeException
• 运行时异常用于表示程序运行时发生的错
误, 不应该被捕捉; 在程序退出(main)时会调
用该异常的printStackTrace方法;
• 与被捕捉异常不同的是, 如果一个方法会抛
出运行时异常, 不需要在方法声明中指定抛
出异常; 常见的运行时异常有:
NullPointerException, ArraylndexOutOfBoundsException
• 示例: demo/Demo6.java
- 16. finally块
• 语法格式:
1, try {...}catch(...) {...} finally {...}
这里可以有多个catch块
2, try {...} finally {...}
• finally块用于确保某段代码被执行, 而不管try块
是否抛出异常; 执行顺序是: 最先执行try块的代
码, 如果有catch块则执行catch块, 最后执行
finally块;
• finally块通常用于确保某些资源被释放, 比如数
据库连接, 文件句柄等;
• 示例: demo/Demo7.java
- 17. finally块
& return
• 如果在try/catch块中使用了return语句结束
方法的调用, 那么finally子句会不会执行? 答
案是: finally语句会在return之前执行. 示例:
try {
...;
} catch(Exception ex) {
...;
return;
} finally {
...; // 会被执行
}
• 示例: demo/Demo8.java