关于java异常的整理

news/2024/11/8 17:05:04/

文章目录

  • 一、异常分类
  • 二、throw、throws、try-catch-finally
  • 三、CglibAopProxy中对异常的处理
  • 4、关于UndeclaredThrowableException

一、异常分类

java异常层级结构

  • Throwable:所有异常的根接口
    • Error:严重错误,程序无法处理和恢复
      • 例如VirtualMachineError,OOMError等
    • Exception:异常,程序可以捕获并可能恢复
      • RuntimeException: 运行时异常,无需强制捕获
        • NullPointerException
        • ClassCastException
        • ArithmeticException
        • IllegalArgumentException
      • IOException: IO操作异常
        • FileNotFoundException
        • SocketException
      • SQLException: SQL数据库访问异常
      • TimeoutException: 超时异常
      • ParseException: 解析错误异常
      • OtherException: 其他领域特定的异常
        • HttpException
        • ASFException
      • 自定义Exception:用户自定义的业务异常

从另一个角度看java异常分为Checked Exception和Unchecked Exception

  • Checked Exception: 需要捕获或者声明抛出的异常,如果没有处理则不能编译通过。主要包括Exception及其子类,不包括RuntimeException。例如IOException、SQLException等。
  • Unchecked Exception: 不需要强制捕获的异常,可以不处理。主要包括RuntimeException及其子类。例如NullPointerException、ClassCastException等

Checked Exception举例:

public class Test{public static void main(String[] args) throws IllegalAccessException {int a = new Random().nextInt(10);System.out.println(a);if(a % 2 == 1){throw new IllegalAccessException("This is an checked exception.");}}
}

这里如果不声明(throws)或捕获(try-catch)异常编译会报错

在这里插入图片描述
加上throws IllegalAccessException编译通过,运行结果如下
在这里插入图片描述

Unchecked Exception举例:

public class Test {public static void main(String[] args){int a = new Random().nextInt(10);System.out.println(a);if(a % 2 == 1){throw new IllegalArgumentException("This is an unchecked exception.");}}
}

这里没有throws或try-catch编译通过
在这里插入图片描述
运行结果如下
在这里插入图片描述
ps::注意上面例子上两种异常(IllegalAccessException和IllegalArgumentException),不要看错了

二、throw、throws、try-catch-finally

  • throw: 用于抛出一个异常对象,通常在方法体内使用。

例如:

throw new IOException("文件读取错误");
  • throws: 声明一个方法可能抛出的异常类型,出现在方法签名中。

例如:

public void readFile(String file) throws IOException {// 方法实现
}
  • try-catch-finally: 用于捕获异常,try代码块表示需要捕获异常的代码,catch表示捕获到异常后的处理逻辑,finally表示需要额外处理的逻辑
    finally中的内容是一定会执行的,无论有没有捕获异常。常用于关闭IO流等做一些收尾操作。

例如:

try {readFile(file); 
} catch (IOException e) {// 处理IO异常
} finally {// 额外逻辑
}

三、CglibAopProxy中对异常的处理

在CglibAopProxy中有一个内部类CglibMethodInvocation,而CglibMethodInvocation中的proceed()方法对捕获的异常做了一个逻辑处理

        @Nullablepublic Object proceed() throws Throwable {try {return super.proceed();} catch (RuntimeException var2) {// RuntimeException或其子类直接抛出 ---- 1throw var2;} catch (Exception var3) {// 非RunTimeException需根据Cglib代理的方法抛出的异常判断 ---- 2// 是代理方法抛出的异常或该异常的子类则 ---- 3// 若不是则抛出UndeclaredThrowableException异常 ---- 4if (!ReflectionUtils.declaresException(this.getMethod(), var3.getClass()) && !KotlinDetector.isKotlinType(this.getMethod().getDeclaringClass())) {throw new UndeclaredThrowableException(var3);} else {throw var3;}}}

上述代码2、3、4实现主要由if语句条件中ReflectionUtils.declaresException()方法实现
方法参数:
Method method:代理的方法
Class<?> exceptionType:抛出的异常(不是代理方法抛出的),这里是aop中抛出的IllegalAccessException

    public static boolean declaresException(Method method, Class<?> exceptionType) {Assert.notNull(method, "Method must not be null");// 获取代理方法中抛出的异常类型Class<?>[] declaredExceptions = method.getExceptionTypes();Class[] var3 = declaredExceptions;int var4 = declaredExceptions.length;// 判断捕获的异常是否是代理方法抛出的异常或该异常子类for(int var5 = 0; var5 < var4; ++var5) {Class<?> declaredException = var3[var5];if (declaredException.isAssignableFrom(exceptionType)) {return true;}}return false;}

举例说明:
这里自定义注解+aop切面增强某个controller方法时抛出了IllegalAccessException异常
在这里插入图片描述
controller中并未throws任何异常
在这里插入图片描述
运行结果
在这里插入图片描述
返回给前端的结果也是这个,并没有返回我们写的IllegalAccessException
打断点调试
先走到CglibAopProxy这
因为IllegalAccessException不是RuntimeException的子类,所以走到了if条件语句这
在这里插入图片描述
进入到ReflectionUtils.declaresException()方法
在这里插入图片描述
查看控制台debug的内容可知他从method中获取的异常类型
在这里插入图片描述
可见是没有获取到任何异常的,因为上面controller中并未手动抛出任何异常
所以最后ReflectionUtils.declaresException(this.getMethod(), var3.getClass())返回的结果是false
抛出UndeclaredThrowableException异常
看名字能知道这个异常的意思是未声明的异常

4、关于UndeclaredThrowableException

一文搞懂 UndeclaredThrowableException


http://www.ppmy.cn/news/1007884.html

相关文章

ABP 后台任务生产者-消费者模式的实现逻辑

ABP 的后台任务是通过生产者-消费者模式来实现的。 在 ABP 中&#xff0c;生产者通过调用 IBackgroundJobManager 接口的 AddJobAsync 方法来添加后台任务&#xff0c;消费者则通过调用 IBackgroundJobExecuter 接口的 ExecuteAsync 方法来执行后台任务。当生产者添加一个后台…

Java阶段五Day21

Java阶段五Day21 文章目录 Java阶段五Day21问题解析rocketmq清空数据 linux学习背景什么是linux系统虚拟机介绍启动 虚拟机linux虚拟机网络的问题 linux系统的基础命令命令提示符命令格式pwd指令ls指令cd指令mkdirtouch指令cp指令rm指令mv指令cat指令tail指令 文本编辑器vim操作…

css position: sticky;实现上下粘性布局,中间区域滚动

sticky主要解决的问题 1、使用absolute和fixed中间区域需要定义高度2、使用absolute和fixed底部需要写padding-bottom 避免列表被遮挡住一部分&#xff08;底部是浮窗的时候&#xff0c;需要动态的现实隐藏&#xff09; <!DOCTYPE html> <html lang"en"&…

前端学习记录~2023.7.26~JavaScript重难点实例精讲~第3章 函数

第2章 引用数据类型 前言3.1 函数的定义与调用3.3.1 函数的定义&#xff08;1&#xff09;函数声明&#xff08;2&#xff09;函数表达式&#xff08;3&#xff09;Function()构造函数&#xff08;4&#xff09;函数表达式的应用场景&#xff08;5&#xff09;函数声明与函数表…

【深度学习】在 MNIST实现自动编码器实践教程

一、说明 自动编码器是一种无监督学习的神经网络模型&#xff0c;主要用于降维或特征提取。常见的自动编码器包括基本的单层自动编码器、深度自动编码器、卷积自动编码器和变分自动编码器等。 其中&#xff0c;基本的单层自动编码器由一个编码器和一个解码器组成&#xff0c;编…

Docker学习(二十四)报错速查手册

目录 一、This error may indicate that the docker daemon is not running 报错docker login 报错截图&#xff1a;原因分析&#xff1a;解决方案&#xff1a; 二、Get "https://harbor.xxx.cn/v2/": EOF 报错docker login 报错截图&#xff1a;原因分析&#xff1a…

基于 yolov8 的人体姿态评估

写在前面 工作中遇到&#xff0c;简单整理博文内容为使用预训练模型的一个预测 Demo测试图片来源与网络,如有侵权请告知理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停…

NLP实践——使用Llama-2进行中文对话

NLP实践——使用Llama-2进行中文对话 1. 前言2. 利用prompt3. 利用Logit Processor3.1 修改13.2 修改23.3 修改33.4 修改4 1. 前言 在之前的博客 NLP实践——Llama-2 多轮对话prompt构建中&#xff0c;介绍了如何构建多轮对话的prompt&#xff0c;本文将介绍如何使用Llama-2进…