一、处理异常
(一)异常分类
未检查异常:不一定非要抛出或捕获的异常(不可控制或应该避免发生)
Error:Java运行时系统的内部错误,资源耗尽错误。(不可控制)
RuntimeException:程序错误导致的异常。比如数组越界,空指针等。(应避免发生)
已检查异常:必须抛出或捕获的异常
IOException:其他错误导致的异常。
(二)声明异常
发生无法处理的情况就可以抛出异常,说明可能发生什么错误。
抛出异常的情况:
1.调用了抛出已检查异常的方法(在方法首部声明异常,否则没有处理器捕获异常,当前线程结束)
2.程序运行过程中出现错误,并用throw抛出已检查异常(在方法首部声明异常,否则没有处理器捕获异常,当前线程结束)
3.程序出错
4.Java虚拟机和运行时库出现内部异常(不需要声明)
子类重写父类方法时不能抛出范围更大的异常。
(三)抛出异常
步骤:找到合适的异常类,创建对象,抛出对象
抛出即可,不用继续处理了。
例:文件输入过程中抛出EOFException
String readData(Scanner in) throws EOFException{
……
if(!in.hasNext()){
if(n < len){//文件读取过程中意外中断,抛出EOFException异常
throw new EOFException();
}
}
return s;
}
EOFException 中还有含字符串参数的构造方法,描述出现异常的情况。
(四)创建异常类
标准异常类无法充分描述的异常则用自定义异常类描述,只需定义派生于Exception或其子类的类。定义两个构造方法,一个默认的,一个有String参数的。
class FileFormatException extends IOException{
public FileFormatException(){}
public FileFormatException(String message){
super(message);
//调用父类Throwable的有参构造方法,其中Throwable重写了toString方法,打印message
}
}
二、捕获异常
若try语句块中代码抛出catch语句块中异常类型,则执行catch子句中处理器代码,否则跳过catch语句块。
try{
code
}
catch(ExceptionType1 e1){
handler for this type
}
e1.getMessage();//获得与异常有关的更多信息
catch(ExceptionType2 e2){
...
}
catch(ExceptionType3 e3){
...
}//可以捕获多个异常
捕获知道如何处理的异常,抛出不知如何处理的异常(throws)
(一)再次抛出异常&异常链
在catch子句中抛出异常,改变异常的类型。(仅表示有故障,不显示细节)
try{
...
}
catch(SQLException e){
//使用这种包装技术既能抛出高级异常又不会丢失原始异常的细节
Throwable se = new ServletException("database error");
se.initCause(e);
throw se;
//捕获到异常后,则如下重新得到原始异常
Throwable ee = se.getCause();
}
(二)finally子句
无论是否抛出异常,finally子句都执行。
Graphics g = image.getGraphics();
try{
//1
code that might throw exceptions
//2
}
catch(IOException e){
//3
show error dialog
//4
}
finally{
//5
g.dispose();
}
//6
代码未抛出异常:执行1、2、5、6。
抛出catch子句捕获的异常: 1、3、4、5、6(catch子句未抛出异常) 1、3、5(catch子句抛出异常),并将异常抛回给方法调用者
try语句未抛出catch子句捕获的异常: 1、5,并将异常抛回给方法调用者
用finally子句关闭资源。
finally子句的返回值会覆盖try、catch子句中的返回值,
finally子句抛出异常时会覆盖catch子句抛出的异常,
finally子句中有 return时会忽略catch子句抛出的异常。