12_异常

异常的体系结构

在这里插入图片描述
Throwable:指所有错误和异常的祖先类

按照错误的严重程度分类

  • Error:比较严重的错误,代码处理不了的、JVM内部资源耗尽的错误
    • java.lang.StackOverflowError:栈溢出
    • java.lang.OutOfMemoryError:堆溢出
  • Exception:错误程度小, 能够用代码进行处理
    • java.lang.ArithmeticException:/ by zero: 算数异常 /0
    • java.lang.NullPointerException:空指针异常
    • java.lang.ArrayIndexOutOfBoundsException:数组越界

根据处理方式的不同分类

  • 编译时异常:编译不通过(除了RuntimeException及其子类外的其他的异常)
  • 运行时异常:编译通过, 但是运行时可能会出错(RuntimeException及其子类)

Exception是运行时异常还是编译时异常

  • Exception是编译时异常和运行时异常的父类
  • 自定义异常的时候,Exception作为编译时异常

在这里插入图片描述


异常处理

JVM默认处理流程

  1. 当我们代码在执行到,发生错误的地方。
  2. 一旦发生错误,jvm就会终止我们自己程序的运行,转而执行jvm自己的错误处理流程
  3. 在发生错误地方,收集错误信息,产生一个描述错误的对象
  4. 访问收集到的错误信息,将错误信息,输出到控制台窗口中

执行过程

  • 如果错误产生在main方法
    • 当我们的代码执行到错误行数之前,代码是正常执行的
    • 当我们的代码执行到错误行数时,JVM会终止程序的执行,抛出一个该异常信息封装成的对象
    • 将该对象中的异常信息,打印到控制台上,告诉程序员发生了什么问题
    • 发生错误之后的语句,都不执行了
  • 如果错误产生在main方法当中的另一个方法中
    • 当程序执行到该方法的错误行数时,JVM会终止程序的执行
      • 向上给方法的调用者抛出一个该异常信息封装成的对象
    • 一直向上抛出,直到抛给main方法,main方法最终抛给JVM
    • 发生异常之前的语句正常执行,但是之后的语句都不执行了
  • 默认处理机制仅针对运行时异常

捕获异常,自己处理

try-catch

可以使用快捷键:ctrl + alt + t

  1. 单分支

方式一:
try{
   // 可能出现异常的代码 
}catch(异常类型 对象名){
   // 对异常的处理操作 
}

-----------------------------------------------

方式二:
try{
   // 可能出现异常的代码 
}catch(异常类型1 | 异常类型2 | 异常类型3 | 对象名){
   // 对异常的处理操作 
}

举例


try{
   System.out.println(10/0); 
}
catch(ArithmeticException | NullPointerException e){
    System.out.println(”出现异常“);
}

注意:catch代码块中的代码,只有try块中的代码执行出错时,才会执行!

捕获异常信息

getMessage()
   // 获取异常信息,返回字符串。
   
toString()
   // 获取异常类名和异常信息,返回字符串。
    
printStackTrace()
   // 获取异常类名和异常信息,以及异常出现在程序中的位置,并打印到控制台

举例


try{
   System.out.println(10/0); 
}
catch(ArithmeticException | NullPointerException e){
   System.out.println(e.getMessage());
   System.out.println(e.toString());
   e.printStackTrace();
}

  1. 多分支
try{
   // 可能出现异常的代码 
}
catch(异常类型 对象名){
   // 对异常的处理操作 
}
catch(异常类型 对象名){
   // 对异常的处理操作 
}
catch(异常类型 对象名){
   // 对异常的处理操作 
}.....

注意
如果说,在多catch分支的情况下,如果不同的catch分支,处理的异常类型,有父子关系。那么就一定要注意,处理子类的异常分支写在前面父类的异常分支写在后面


抛出异常,上层处理

throws关键字

概念
方法定义时使用,声明该方法可能抛出的异常,对于编译时异常,可以在语法层面强制方法调用者处理该异常。

语法修饰符 返回值 方法名(形参列表) throws 异常列表 {}

说明

  • 异常列表异常类型1, 异常类型2, .... ,用逗号隔开,列表中的异常不要出现父子关系,如果有,那么编译器只会强制处理父类
  • throws + 运行时异常没有意义,因为运行时异常会自动抛出,不需要声明
  • throws + 编译时异常有意义,这实际上是编译异常处理的一种方式,在方法中声明throws + 编译时异常,声明可能抛出编译时异常,该方法被调用时就要处理这个编译异常
  • 处理编译时异常
    • 方法内部try-catch
    • throws向上抛,如果在main中就别抛了,处理一下

子类重写父类方法注意:

  • 子类方法不能比父类抛出更多的编译时异常
  • 父类如果抛出Exception,那么子类就可以随便抛出
  • 建议子类重写的时候保持跟父类一样的异常列表

throw关键字

概念

  • 方法体中使用
  • 主动在程序中抛出异常
  • 每次只能抛出确定的某个异常对象

针对运行时异常

throw + 运行时异常对象(new 创建出来的)

eg:

throw new ArithmeticException(”出现了算数异常“);

针对编译时异常
需要结合throws关键字一起使用,不要这里处理,交给方法的调用者处理(这里直接enter + alt

throw + 编译时异常对象(new 创建出来的)

eg:

private static void func() throws CloneNotSupportedException{
	throw new CloneNotSupportedException(”出现了clone异常“);
}

throws VS throw

throws

  • 用在方法声明后面,跟的是异常类名
  • 可以跟多个异常类名,用逗号隔开
  • 表示抛出异常,由该方法的调用者来处理
  • throws表示出现异常的一种可能性,并不一定会发生这些异常

throw

  • 用在方法体内,跟的是异常对象名
  • 只能抛出一个异常对象
  • 表示抛出异常,可以由方法体内的语句处理
  • throw则是抛出了异常,执行throw则一定抛出了某种异常

finally

概念
被finally控制的语句体一定会执行,用于释放资源,在IO流操作和数据库操作中会见到

语法

方式一:
try{
    
}catch(){
    
}catch(){
    
}.....
finally{
    // 一定执行
}


方式二:
try{
    
}finally{
    
}

  • try代码块如果有return
    • 程序会先执行完finally代码块,回过头执行try中的return
  • catch代码块中如果有return,并且catch正常捕获异常执行
    • 程序会先执行完finally代码块后,再回去执行catch中return,从catch代码块中结束方法
  • finally代码中有return
    • 不会影响finally代码块执行
  • 如果finally和catch中都有return
    • 程序会直接从finally代码块中的return结束方法
  • 如果try中的异常不能正常捕获,但是finally中有return
    • 注意此时程序会跳过这个异常,不会抛出异常给JVM报错

final VS finally VS finalize

  • final关键字,最终的,最后的。可以修饰类 成员变量 成员方法
    • 修饰,该类不能被继承
    • 修饰变量表示一个常量
    • 修饰方法表示无法重写的方法
  • finally代码块,和try…catch一起使用,具有必然执行的特点
    • 异常处理体系当中,用于资源释放
  • finalize方法,作用是作用是在垃圾回收器回收对象之前,允许对象执行一些清理操作。

异常策略选择

  • 运行时异常,应当在代码的测试阶段修改代码
  • 编译时异常,功能内部能够处理的就处理,如果不能够或者没有必要处理,就throws关键字向上抛出

自定义异常

概念:现有的异常体系不满足需求

自定义编译时异常

  • 定义一个类继承Exception
  • 构造方法

eg:

// 定义编译时异常

class MyException1 extends Exception{
    public MyException1() {
    }

    public MyException1(String message) {
        super(message);
    }
}

自定义运行时异常

  • 定义一个类继承RuntimeException
  • 构造方法

eg:

// 定义运行时异常

class MyException2 extends RuntimeException{
    public MyException2() {
    }

    public MyException2(String message) {
        super(message);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coo1heisenberg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值