java异常

文章详细介绍了Java中的异常概念,包括Exception和Error的区别,异常的分类(编译时异常和运行时异常),以及异常的处理方式,如try-catch-finally结构,throw和throws的使用。同时讨论了finally块的执行保证及其在方法重写中的规则。
摘要由CSDN通过智能技术生成

一、基本概念

异常就是程序执行时不正常的现象
异常的出现是为了提升程序健壮性
java 中异常以类的形式出现

异常的继承关系图,Exception 是所有异常的基类。(Error 指错误)
Exception 和 Error 的区别:

  • Exception是 java 程序运行中可预料的异常,可以人为干预抛出 和 捕捉;
  • Error 指不可预料的错误,会直接导致 JVM 不可处理或不可恢复所以这种异常不可能抓取到,比如OutOfMemoryError、NoClassDefFoundError等。

在这里插入图片描述

一、异常分类

注意:异常的产生是 new 出异常对象,所以异常是运行时产生的

  1. 编译时异常

指必须在编写程序时预先处理的异常,如果不处理编译器会报错
编译时异常发生的概率比较高
因为需要预先处理,也称『受检异常』、『受控异常』

  1. 运行时异常

在编写程序时非必须处理异常,可以处理也可以不处理
运行时异常发生的概率比较低
因为不需要预先处理,也称『未受检异常』、『非受控异常』

三、异常的处理方式

以下面这段代码举例:

  • 当程序非正常执行时, 100/i 这行代码会抛出 ArithmeticException 异常(该异常属于运行时异常)
  • 执行这行代码的 main 方法接收异常,main 方法没有对异常进行处理,继续上抛至 jvm
  • jvm 终止程序
public class ExceptionTest {
    public static void main(String[] args) {
        int i = 0;
        System.out.println( 100/i);
    }
}

扑获异常 or 抛出

如需上层处理异常时,则可以将异常抛出,其他情况需要处理异常

  • try 包裹可能抛出异常的代码块, catch 捕获异常,并处理(调用者不感知异常
  • finally 异常处理时一定会被执行的代码,一般用来资源释放等等
  • throw 主动抛出异常
  • throws 声明异常,上报给调用者,表示可能要抛出该异常(调用者感知异常
public class ExceptionTest {
    public static void main(String[] args) throws NullPointerException{
        try {
            test1();
        } catch (ArithmeticException e) {
        	// e引用 保存的内存地址是那个new出来 异常对象的内存地址
            System.out.println(" 捕捉 ArithmeticException 异常");
        }finally {
            // finally 语句中的代码一定会被执行
            System.out.println("finally 语句中的代码一定被执行");
        }

        // throw 关键字用来抛出 异常对象
        throw new NullPointerException("主动抛出 空指针 异常");
        
        // 下面程序不处理 NullPointerException 而是直接上抛
    }

    // throws 关键字只是声明异常,表示可能要抛出该异常
    public static void test1() throws ArithmeticException {
        int i = 0;
        System.out.println(100 / i);
    }
}

深入 try catch

  • catch 后面可以是具体的异常类,也可以是该异常类型的父类型(多态)
  • catch 可以有多个,也可以同时捕捉多个异常,建议分多个捕捉,便于调试
  • catch 分多个写的时候需要由细到粗

深入 finally

1、finally 必须和 try 搭配使用(try catch --> finally)\(try --> finally)
2、finally 失效场景,执行前调用 System.exit(0); 退出JVM之后,finally语句中的代码就不执行了

3、finally 代码为什么一定会被执行?

  • 在程序执行中,不一定会抛出异常时,会将 finally 的代码拷贝到 try 模块的最后,也会拷贝到 catch 模块的最后来确保代码一定会被执行。
  • 在程序执行中,如果一定会抛出异常,则执行顺序是(try --> catch --> finally)\(try --> finally)。
    • 如何理解:这里 finally 相当于一个 catch ,他捕获 (try catch) 块中所有的异常(catch 中捕获 try 块中的所有异常)。对于一定会异常的块中,则一定会在 catch 中捕获,所以不需要将代码进行拷贝。

举例一:返回 i= 1

public static int test2() {
        int i = 0;
        try{
            i = 1;
            // 会将 finally 模块的 i = 2;复制过来执行,但是执行只影响 finally 模块局部变量的值
            // i = 2;
            // 此处返回的 try 模块的局部变量 i = 1
            return i;
            
        }finally {
            // 此处对 finally 模块的局部变量 i 进行赋值为 2 
            i = 2;
        }
        // 该行代码不会被执行
        // System.out.println(100 / i);
    }

4、finally 代码为什么不能 return ?
因为上面 finally 的代码一定会被执行的原因,可能导致 代码覆盖。
举例:i=2

 public static int test2() {
        int i = 0;
        try{
            i = 1;
            // 会将 finally 模块的代码复制过来执行,执行影响 finally 局部变量的值
            // 但是由于有 finally 中有 return,最后返回的的 finally 局部变量的值, 将 try 模块中的计算结果丢掉了
            // i++;
            // return i;
            return i;

        }finally {
            // 此处对 finally 模块的 局部变量 i 进行赋值为 2
            i = 2;
            return i;
        }
        // 该行代码不会被执行
        // System.out.println(100 / i);
    }

java 继承方法重写与异常

子类重写父类方法时如果要抛出异常,只能抛出比父类异常更宽泛的异常。
这个原因 参考下大佬的文章

我自己实践了一下,没有明白按照这个多态的原理,为什么父类没有抛出异常时,子类可以抛出异常。????

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值