异常
继承体系
- Throwable 错误和异常的根类
- Error:是严重的问题,不应该试图去捕获
- Exception:应该试图去捕获
- RuntimeException 运行时异常
Exception分为两类:
一类称为编译时异常(受检异常)Exception中除了RuntimeException以外的异常;
另一类称为运行时异常(非受检异常)RuntimeException及其子类。
异常执行过程
当程序执行到某一行时,产生错误,首先尝试内部解决,如果内部能解决就解决,不能解决就向上找调用者, 调用者也是先尝试自己解决不能解决继续向上找,以此类推直至找到jvm,jvm将异常名、异常信息、异常出现位置这些信息返回到控制台。
异常处理
捕获异常
真正的通过代码等方式处理问题
格式
try{
可能会出现异常的代码
}catch(异常类型 异常对象名称){
处理异常的代码
// 如果没有需求,finally 可以不写
}finally{
一定会执行的语句
释放资源操作的代码
}
try可以和多个catch进行组合,catch小括号中的异常名,从上向下看类型逐渐增大,如果是平级的谁在上谁在下无所谓。
无论有无异常,finally都会执行,即使遇到return语句也会执行;只有遇到System.exit(0);时不会执行。
try{
可能会出现异常的代码
// 也可以这样写,但是不建议,尽量把每个异常单独抛出
}catch(异常类型1 | 异常类型2 异常对象名称){
处理异常的代码
// 即使执行return,finally 也会执行
return;
}catch(异常声明){
处理异常的代码
// 只有这种情况才不会执行 finally
System.exit(0);
}finally{
一定会执行的语句
释放资源操作的代码
}
try和finally组合
try {
可能发生异常的代码
} finally {
一定要执行的代码
}
这种结构并不能捕获异常。目的就是想要finally中的代码执行,由于finally不能单独使用,因此需和try组合使用
声明异常
并不是真正的处理,是交给他人处理
throws
用在方法上,告知方法的调用者,该方法可能有问题,使用时需要处理。
格式:
方法名 throws 异常名1,异常名2,异常名3,……
示例:
public void test() throws NullPointerException,IndexOutOfBoundsException{
}
如果声明的运行时异常,则调用时可以处理也可以不处理
如果声明的是非运行时异常,则调用时必须处理,
处理方式两种:
1.捕获
2.继续向上声明throws
throw
用在方法内,主动抛出一个异常对象
如果抛出的是运行时异常,处理或者不处理都可以
如果抛出的是编译时异常,则必须处理,捕获或者是throws都可以,但是一般都选择使用throws,调用该方法时必须做出处理。
格式
throw new NullPointerException();
自定义异常类
定义类继承Exception或者继承RuntimeException
调用父类的构造方法(可选)
示例
import java.util.Scanner;
public class exceptionDemo {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double r = in.nextDouble();
// 处理 getArea 可能存在的异常
try {
getArea(r);
} catch (Exception e) {
System.out.println(e);
}
in.close();
}
// 定义方法,求的圆面积
public static void getArea(double r) throws RadiusLessThanZeroException {
if (r <= 0) {
// 抛出编译时异常,选择不处理,上抛,在方法后添加throws
throw new RadiusLessThanZeroException("半径必须大于零");
} else {
System.out.println(Math.PI * Math.pow(r, 2));
}
}
}
// 自定义异常类 半径小于等于0异常
class RadiusLessThanZeroException extends Exception {
public RadiusLessThanZeroException() {
}
public RadiusLessThanZeroException(String msg) {
super(msg);
}
}
异常在继承中的问题
重写方法时
- 父类方法没有throws子类重写时可以加也可以不加,如果加throws,throws后边只能跟运行时异常
- 父类方法有throws,并且是Exception,那么子类重写时,可以加throws,也可以不加throws,如果加throws,throws后声明的异常与父类相同或者是父类异常的子集都可以