异常分类
Java中的异常层次结构
- Error类层次结构描述了Java运行时系统内部错误和资源耗尽错误(此情况较少出现,并且基本无能为力;重点关注Exception异常)。
- Exception
- IOException
- 表示程序以外的错误(其他异常),如:试图超越文件末尾继续读取数据、试图打开一个不存在的文件、试图根据给定的字符串查找并不存在的类对象。
- RuntimeException
- 由编程错误导致的异常,如:错误的强制类型转换、数组访问越界、访问null指针。
- Java语言规范将派生于Error类或RuntimeException类的所有异常称为非检查型异常,所有其他的异常称为检查型异常(编译器将提醒你声明或捕获一个可能将要发生的异常)。
如果出现RuntimeException异常,那么就一定是你的问题
声明异常
throws ...
public class ThrowableTest {
//根据给定的参数获取一个FileInputStream对象,并进行接下来的操作
public void getFileInputStream(String name) throws FileNotFoundException {
//...
}
}
- 需要声明异常的4种情况
- 调用了一个抛出检查型异常的方法
- 检测到一个错误,并利用throw语句抛出一个检查型异常
- 程序出现错误,如空指针、数组下标越界,会抛出一个非检查型异常
注:不需要声明Java的内部错误,即从Error继承的异常,因为我们对此完全无法控制。同样,也不应该声明从RuntimeException继承的那些非检查型异常,这些运行时错误完全在我们的控制之中,应该多花时间修正错误,而不只是生命这些有可能发生的错误
如果发生异常,该方法将不会得到一个FileInputStream对象,而是抛出声明的异常
抛出异常
throw ...
/*可以感觉到EOFException的用意,因为我们可以往流中放入null值,所以我们没法找到一个不
可能的值来表示到达流的末尾,所以只能通过抛异常的方式来告诉用户到达末尾了*/
public void readDate(Scanner in) throws EOFException{
int index = getStream();
if(index<0){
throw new EOFException();
}
}
- 抛出异常的方法
- 找到一个合适的异常类
- 创建这个类的一个对象
- 将对象抛出
一旦方法抛出了异常,这个方法就不会返回到调用者
捕获异常
try/catch
public void read(String filename){
try{
InputStream in = new FileInputStream(filename);
int b;
while ((b=in.read())!=-1){
//process input
}
}catch (IOException exception){
exception.printStackTrace();
}
}
- 如果try语句块中的任何代码抛出了catch子句中指定的一个异常类,那么
- 程序将跳过try语句块的其余代码
- 程序将执行catch子句中的处理器代码
要捕获那些你知道如何处理的异常,而继续传播那些你不知道怎样处理的异常
finally
public void read(String filename){
InputStream in = null;
try{
in = new FileInputStream(filename);
int b;
while ((b=in.read())!=-1){
//process input
}
}catch (IOException exception){
exception.printStackTrace();
}finally {
try {//内层try语句块只有一个职责,就是确保关闭输入流,并报告finally子句中可能出现的错误
in.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
- 无论在try语句块中是否遇到异常,finally子句中的in.close()语句都会执行。
- 如果finally语句块中也抛出一个异常,这个异常将会被重新抛出,并且必须由另一个catch子句捕获
在实际中,try-with-resources语句可能比finally子句更常用