1.简介
在Java中,异常具有自己的语法和特定的继承结构。异常对象都是派生于Throwable类的一个实例,当然也可以自定义异常。层次结构如图
层次
- Error类层次:描述Java运行时系统的内部错误和资源耗尽错误。
- RuntimeException层次:由于程序错误导致的异常。
- 其他层次:程序本身没有问题,像IO错误导致的其他异常。
常见的运行时异常
类型转换错误,数组越界错误,访问null指针(在使用变量前检查是否为null,来杜绝)
分类 - 非受检异常:Error类或RuntimeException类的所有异常。
- 受检异常:其他所有。
声明受检异常
一般下面的四种情况应该在方法上通过throws字句声明异常
- 调用一个抛出受检异常的方法
- 运行发生错误,且利用throw语句抛出受检异常
- 程序出现错误
- 虚拟机和运行时库出现内部错误
注意:子类方法中声明的异常应该更具体。
抛出异常
- 找到合适的异常类
- 创建这个类的对象
- 将对象抛出
创建异常类
新建一个类,继承自Exception或其子类,定义空参构造器和一个详细构造器。
class XxException extends IOException{
public XxException(){}
public XxException(String s){
super(s);
}
}
2 捕获异常
try/catch
- 如果发生异常了但没有捕获,程序终止并打印异常信息,要捕获异常需使用try/catch
- 如果try语句中的代码抛出了一个catch子句中说明的异常类,那么程序跳过try中的其余代码并执行catch子句的处理器代码;如果没有抛出任何异常那么跳过catch语句;如果抛出了catch中没有声明的异常,那么就会推出方法。
- 如果不知道如何处理,使用throws将异常传递给调用者。
捕获多个异常
- 每个异常写一个catch
try{...}
catch(Xxx e){...}
catch(Xxx e){...}
...
- java7之后可以合并catch语句,注意,需要彼此之间不存在子类关系
try{...}
catch(XXX|XXX e){...}
当然了,在catch中还可以继续抛出异常,这样做可以改变异常的类型,或者只是想单纯的记录异常,重新抛出,而不做改变
finally字句
在退出方法之前回收资源。不管是否有异常被捕获,finally子句的代码都被执行。
将try/catch和try/finally耦合,这样设计,内层try中负责关闭资源,外层try负责报告错误,包括finally中的异常。
try{
try{
...
}
finally{
...关闭资源
}
}
catch(XXXException e){
...处理异常
}
注意:如果在finally中有return的话,会覆盖try中ruturn,方法返回值就是该return。
带资源的try语句
如果finally也抛出异常,那么原始异常就丢失了。
可以使用AutoCloseable接口。只要try退出时就会自动关闭资源。
try(PrintWriter po=new PrinterWriter("t.txt");...){
...
}
异常使用
1.不要滥用try/catch语句,会花费更多的时间。
2.不要只抛出RuntimeException,只捕获Thowable异常。
3.早抛出,晚捕获。