10.Java中如何处理异常
1、介绍
1.1 概念:
异常,就是不正常情况;程序中出现不符合预期的情况就是异常;
1.2 作用:
- 可以针对程序中出现的问题作出相应处理,提高程序健壮性;
- 在程序中发生异常的地方通过日志技术将问题记录下来,帮助开发者快速排查错误;
2、异常体系&分类
2.1 体系
Throwable
:java异常体系的最高父类;java中所有可被抛出、捕获或声明的异常类,都要继承这个类或它的子类;Error
:错误,表示程序中严重的不能被JVM处理的问题;遇到这种问题,JVM都会停止运行;Exception
:异常,表示程序中可以被JVM处理的问题;如果程序中抛出该类或它的子类的异常,编译时就会检查有没有书写处理的代码;如果没有写,就会报错;RuntimeException
:表示运行时异常;该类和它的子类表示的异常,在编译期不会检查;- 非
RuntimeException
:表示编译期异常;
2.2 分类
- 编译期异常
- 概念:指的是
Exception
及其子类(不包括RuntimeException
和它的子类)表示的异常; - 特点:如果在程序中使用
throw
关键字显示的抛出这类异常,编译时编译器会检查有没有书写处理代码,如果没有就会报错;(也就是说,程序中如果抛出这类异常,必须处理)
- 概念:指的是
- 运行期异常:
- 概念:指的是
RuntimeException
和它的子类表示的异常; - 特点:如果程序中使用
throw
关键字显示的抛出这类异常,不管书写处理代码没有,编译时编译器都不管;
- 概念:指的是
编译期异常和运行期异常,指的是编译的时候,是否检查书写了处理代码;
2.3 图解:
3、自定义异常
因为JDK中提供的异常类太多,不方便记忆和使用,所以需要自定义异常
Error
表示 程序中严重的不应该处理的问题;
Exception
表示程序中应该自己能够处理的问题;
所以,一般自定义异常,可以继承Exception
,而不要去继承Error
;
3.1 自定义异常的步骤:
1.定义一个类,让它继承Exception
或RuntimeException
;
2.创建一个构造函数,接收一个表示异常信息的参数;
3.调用父类的有参构造函数,将接收的异常信息传递给父类的构造函数;
4.示例:
//需求:创建一个描述人的信息的类,需要对年龄的合法性进行判断;
class WrongAgeException extends RuntimeException{
WrongAgeException(){}
WrongAgeException(String errMsg){
super(errMsg);
}
}
class Person{
private int age;
public void setAge(int age){
if(age >= 1 && age <= 150){
this.age = age;
}else{
//实际上,如果数据不合法程序就不应该继续向下执行;所以这里应该抛出异常;
throw new WrongAgeException("输入的年龄"+age+"不合法,正确的范围应该是1(包含)到150(包含)");
}
}
public int getAge(){
return age;
}
public Person(int age){
setAge(age);//调用函数赋值,可以在创建对象时也对传入的年龄参数进行检验
}
//重写toString函数,目的是可以直接输出这个对象的属性值
public String toString(){
return "年龄:"+age;
}
}
//测试
class Test{
public static void main(String[] args) {
Person p = new Person(-10);
System.out.println(p);
p.setAge(-2);
System.out.println(p);
}
}
4、异常的处理
4.1 异常的声明:
如果程序不能自己解决出现的问题,就可以使用throws
关键字,在函数的参数列表后面、函数体大括号前面将异常的类型声明出去,目的时告诉调用者,这个函数执行时有可能会出现什么问题;这种处理方法就叫做异常的声明;
自己不处理,告诉调用者,自己可能出什么问题,真出了问题,就将问题抛给调用者;
4.2 异常的捕获:
如果程序中出现的问题可以自己解决,就可以使用try-catch
代码块,将可能出错的代码包起来,然后书写处理代码;这种处理方式叫做异常的捕获;
自己直接将问题解决,不惊动调用者;
看具体情况;一般如果问题是因为传入的参数不合法造成的,就应该使用异常的声明;否则应该使用捕获;
5、异常部分细节
5.1 throw
和throws
的区别
throw
:用来在函数里面抛出异常对象;
throws
:用来声明函数会抛出异常;
5.2 finally
代码块
一般在捕获异常时,在try-catch代码块后面还可以添加一个finally代码块,
作用是:在finally块中的代码,一定会被执行;
一般再开发中,有些工作一定要执行的,都会放到finally代码块中完成;
5.3 try
、catch
、finally
允许的组合
- 必须有try代码块;
- 三个代码块都不能单独存在;
- ry可以和其它两个单独组合,也可以三个一起使用;
- catch可以多次出现;
5.4 继承中方法重写的异常
子类重写父类函数,不能比父类函数声明更多编译期异常;
父类方法没有声明异常,子类重写的方法不能声明编译时异常
父类方法声明了一个编译异常,子类重写的方法只能声明这个异常或它的子异常
父类方法声明了多个编译异常,子类重写的方法只能声明这些异常的子集或子集的子类