异常
什么是异常?
在程序运行过程中出现的错误,称为异常
。异常就是程序运行过程中出现了不正常现象导致程序的中断。
在Java中,把各种异常现象进行了抽象形成了异常类。
异常的继承体系结构
最顶级的 Throwable:错误,异常
Error:错误,正常情况下,不太可能出现的,绝大多数的Error都会导致程序处于一个非正常的状态下,很难恢复。外力的作用下,不考虑。Errorr是Throwable的子类,它是在我们java程序处理范围之外的
Exception:异常,在java语言中,将程序执行中发生的不正常的情况称之为异常。
- 编译期异常:写代码的时候会抛异常。如果编译期不解决,会编译不通过,一直报错。
- 运行期异常:RuntimeException,运行时会抛异常,平时没事。
自定义异常:java中异常机制,但是一旦结合实际的业务,就差的很多了。
怎么自定义异常?
1.所有的异常必须是Throwable的子类(大材小用,没必要)
2.如果要定义一个编译期异常,需要继承Exception类。
//编译期异常
public class MyException extends Exception {
public MyException(String message){
super(message);
}
}
3.如果要定义一个运行期异常,需要继承RuntimeException类
//运行期异常
public class MyRuntimeException extends RuntimeException {
public MyRuntimeException(String message){
super(message);
}
}
- 目前接触的异常
- 下标越界
- 空指针
- 类型转换
- 数字格式化异常
- 算数异常(数学异常)
- 编程界的…
- 除数为零
- 没有关闭资源(如IO流)
- 停电
- 当一个程序抛出异常时,抛异常后面的语句不会执行,类似于return的功能
终止方法的执行
异常处理
- try…catch处理
try{可能产生异常的代码}catch(异常的种类){异常的处理}
处理异常,程序不会停。
public static void main(String[] args) {
try {
int a=10;
int b=0;
int c=a/b;//可能出现异常的语句
} catch (ArithmeticException e) {//异常种类
//打印异常信息
e.printStackTrace();
}
System.out.println("我会执行");
}
- catch可以写多个,有顺序问题
先写小的,再写大的
public static void main(String[] args) {
int num1=10;
int num2=0;
try {
System.out.println(num1 / num2);
//从开发角度来说写指定的
} catch (ArithmeticException e) {//小范围错误
e.printStackTrace();
}catch (Exception e){//大范围错误
System.out.println("未知错误");
}
}
- throw抛出异常
throw抛出运行时异常
public static void fun(int i, int j) {
if (j == 0) {
throw new ArithmeticException("除数不能为0");
}
System.out.println(i / j);
}
在一个语句块中如果使用throw抛出一个编译期异常,必须在方法的声明处使用throws关键字来标记异常类型。
public static void fun(int i, int j) throws FileNotFoundException {
if (j == 0) {
throw new FileNotFoundException();//编译期异常
}
System.out.println(i / j);
}
- throw是可以当作方法的返回值的。
- 开发中,大部分情况下,使用的都是运行期异常!!
public static String show(String str){
if(!Objects.isNull(str)){
return str.concat("hello");
}
throw new MyRuntimeException("参数不能是空");
}
public static void main(String[] args) {
show(null);
}
- 处理异常时,使用
throws
抛出处理:- 谁调用这个方法,谁负责处理该异常
- 在定义方法时,把异常抛出就是为了提醒方法的使用者,有异常需要预处理
class A {
public void a() throws Exception {//a方法抛出异常
}
}
class B {
public void b() throws Exception {
new A().a();//b方法中调用a方法也需要抛出异常
}
}c
class C {
public void c() throws Exception {
new B().b();//c方法中调用b方法也需要抛出异常
}
}
public class Ch05 {
public static void main(String[] args) {
try {//尽量在主方法中处理异常,不要抛出
new C().c();
} catch (Exception e) {
e.printStackTrace();
}
}
}
throws:
如果一个方法它没有捕获一个编译期异常,该方法必须使用throws声明
throws并不是真正解决了异常,只是把异常抛给了下一级调用者。
面试题:
throws 和 throw 区别。
- throws出现在什么地方?
方法的声明处,抛出多个异常,用逗号隔开
finally
finally关键字: finally用来创建在try代码块之后执行的代码块
无论是否发生一异常,finally里面的代码块一定会执行,一般都是用来清理资源的
public static void main(String[] args) {
int num1=10;
int num2=0;
try {
System.out.println(num1/num2);
}catch (ArithmeticException d){
d.printStackTrace();
}finally {
System.out.println("我很重要");
}
}
- 方法的重写
重写的方法不能抛出比被重写方法更大的异常类型
interface Inter01 {
void show() throws MyRuntimeException;
}
public class Ch09 implements Inter01 {
/*@Override
public void show() throws Exception {//错误
}*/
@Override
public void show() throws MyRuntimeException {//正确
}
}