异常
-
分类
- 未检查异常:派生于 RuntimeException类 的所有异常。
- 已检查异常:所有非未检查异常。
- 未检查异常:派生于 RuntimeException类 的所有异常。
-
异常的声明
- 用 throws 关键字 在方法的首部对可能抛出的异常进行声明,可以声明多个异常,中间用 “,” 隔开。
- 一个方法必须声明所有可能抛出的已检查异常。
- 子类覆盖超类的方法,子类方法中声明的已检查异常不能比超类方法中声明的已检查异常更加通用,即子类声明的异常必须是超类声明的异常的本身或其子类。
- 用 throws 关键字 在方法的首部对可能抛出的异常进行声明,可以声明多个异常,中间用 “,” 隔开。
-
抛出异常
- 在方法中用 关键字 throw 抛出一个异常对象 ,方法首部必须声明要抛出的异常。
- 找到一个合适的异常类
- 创建这个类的一个对象
- 将对象抛出
- 在方法中用 关键字 throw 抛出一个异常对象 ,方法首部必须声明要抛出的异常。
-
创建异常类
- 定义一个派生于 Exception 类或者其子类的类,定义的类包含两个构造函数,一个是默认的构造器另一个是带有详细描述信息的构造器。
- 定义一个派生于 Exception 类或者其子类的类,定义的类包含两个构造函数,一个是默认的构造器另一个是带有详细描述信息的构造器。
例:
class FileFormatException extends IOException{
public FileFormatException() {}
public FileFormatException(String gripe){
super(gripe);
}
}
-
捕获异常
- 捕获单个异常
try{
........
}
catch(ExceptionType e)
{
.............
}
捕获多个异常
try{........
}
catch(IOEception e)
{
.............
}
catch(FileNotFoundException e)
{
.............
}
或
try{
........
}
// 注:捕获的异常之间不存在子类关系。
catch(IOEception | UnknownHostException e) //e 自动默认为final变量
{
.............
}
catch(FileNotFoundException e)
{
.............
}
可以在 catch 语句中抛出一个异常 ,这样可以实现异常的包装,这种技术在开发用户子系统的时候既可以抛出子系统的高级异常,还不会丢失原有的异常
- 应用 catch 语句可以实现对异常进行记载后再抛出。当函数声明的异常比 catch 中捕获的异常对象所属的类更加具体的时候,系统会自动检测追踪到try块中,只要try块中只有所声明的异常类对象,并且在catch中没有改变,就是合法的。
-
finally子句
- 不管捕获异常语句怎样执行,最后都要执行finally子句。
- finally子句中的异常和返回值会覆盖前面异常捕获子句中抛出的异常和返回值。
- finally子句中也有可能抛出一个异常。
- 当catch中有return语句时先执行finally语句再执行return语句
-
带关闭资源的try语句
- try(Recource res = ......){
........
} //当然可以指定多个资源,中间用“,” 隔开。
- 当try块退出时会自动关闭资源。
- 当自动关闭资源的时候也可能抛出异常,但是这些异常将会“被抑制”,也就是说不会影响原来的异常的抛出,这一点优于使用finally子句。
- 带资源的try语句还可以有 finally 和 catch ,不过要在资源关闭之后才会执行。
- try(Recource res = ......){
-
注意
- 异常处理所需要的计算机硬件资源比较多,花费时间比较长,所以,能够使用简单的测试或验证语句解决的问题尽量不用异常。
- 在编写代码的时候尽量不要将异常过分细化。频繁的为每一个具体的异常添加try语句块,这样会使代码可读性降低,适当的将异常泛化。
- 在使用异常时要灵活变通,选择合适的异常类型。
- 早抛出,晚捕获。能暴露问题的尽量暴露。
- 该处理的异常就处理。