终于有人把一切都拿走了Java总结了异常处理方法

智聪说说网
智聪说说网
智聪说说网
43262
文章
0
评论
2023-01-1222:27:12 评论 9

最近专门负责团队的项目质量。在治疗异常日志的过程中,我总结了一下Java异常处理。以上是我最近整理的常见异常知识地图。

从异常知识地图最左边的根开始,地图从左到右有真正的父子关系java通过继承实现(除非非RuntimeException虚拟父节点)。

Java所有异常的父类都是Throwable,它又分为Error和Exception。Error如果程序判断执行,则为程序判断XX至少逻辑应该是JVM层面有问题。不应发生在正常情况下。Exception这意味着环境没有问题。Exception请开发人员自己做。Exception分为RuntimeException异常运行和非运行。说到这里,我们从另一个维度对异常进行分类。Java异常分为异常检查和非异常检查。Error和RuntimeException以及RuntimeException子类是非检查异常。其一种是异常检查。这很容易区分。在写Java编译器提示代码时需要编译器提示try catch或者throws检查异常。其他是非检查异常。后面在具体代码实现里有体现。

异常分为异常检查和非异常检查。 我做了一些典型的异常场景demo,上传到了github,地址:

https://github.com/xiexiaojing/yuna

用统一的截面截获异常:

@RestControllerAdvice public class ControllerThrowableAdvice{ @ExceptionHandler(Throwable.class) public String handleThrowable(Throwable e){ return "ControllerThrowableAdvice消息:" e.toString(); } }

Error

Error子类一般不用于捕获,用于抛出。因为Error这意味着环境有问题,是时候停下来维修了。因为Error发生意味着环境有问题,应该停止维护。所以一般的处理是一旦发生Error,会停止JVM。也就是说,平时看到的程序起不来。如下java.awt.image.Kernel的源码。

Error在常用的类库中,除手工抛出外,无黑科技无法稳定复现。所以我的测试类是这样写的

@GetMapping("/errorThrowable") public String showErrorThrowable(){ Error error = new Error("人工抛出一个Error"); throw error; }直接访问页面结果

ControllerThrowableAdvice消息:

org.springframework.web.util.NestedServletException:Handler dispatch failed; nested exception is java.lang.Error: 人工抛出一个Error

上述错误消息意味着spring mvc通过其核心逻辑DispatcherServlet没有人能处理这个返回model的,因为直接返回是一个Error。最后显示的消息通过ControllerThrowableAdvice进行展示。最后显示的消息通过ControllerThrowableAdvice进行展示。

注意Error非检查异常,无需显示处理。

NPE

NPE也就是说,空指针异常很常见,很多类别都不对null做支持。直到apache提供了common包专门处理这种情况。防不胜防,项目还是需要时不时的上线处理这个异常。bugfix。

@GetMapping("/npe") public String showNullPointerException(){ new HashSet(null); return prefix "异常未抛出"; }直接访问页面结果ControllerThrowableAdvice消息

:java.lang.NullPointerException这是因为new HashSet的时候传入null。程序走不到return抛出异常。程序走不到return抛出异常。最后显示的消息通过ControllerThrowableAdvice进行展示。

注意NullPointerException非检查异常,无需显示处理。

算数异常

算数异常很常见,比如做除0,会抛出异常

java.lang.ArithmeticException: / by zero,该找数学老师帮我们检查作业了。值得注意的是,如果使用它BigDecimal.divide请直接使用除法divide(BigDecimal divisor, int scale, RoundingMode roundingMode)避免传输三个参数divide(BigDecimal divisor)传输一个参数,因为如果传输的值不会被抛出

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. 根据输入的摄入模式和保留小数点后的位数,采用三个参数的方法对数据进行处理。注意ArithmeticException非检查异常,无需显示处理。注意ArithmeticException非检查异常,无需显示处理。

未声明异常

未声明异常代码量稍大,想知道测试源代码直接去找我github里下载。地址:

https://github.com/xiexiaojing/yuna

抛出异常的原理是使用动态代理时,如果代理类抛出异常。但是却没有throws声明。找不到匹配代理类型的异常类型会被抛出InvocationTargetException。从知识地图上可以看出是非检查异常。最后会被

UndeclaredThrowableException来处理。这是java处理动态代理不优雅。建议喜欢看源码、模仿源码的朋友不要从中学习。

关注运行中抛出异常的打印堆栈

从打印的堆栈可以看出,这是最终的ArithmeticException抛出时被InvocationTargetException捕获。传递原始参数InvocationTargetException继续抛出,最后被抛出

UndeclaredThrowableException捕获。

注意

UndeclaredThrowableException非检查异常,无需显示处理。

非法参数异常

非法参数异常是很多类或者方法自己定义了java一些基本规则以外的规则不符合会抛出的异常。比如java在动态代理的源代码中,不超过65535个接口。否则,非法参数异常将被抛弃。

注意IllegalArgumentException非检查异常,无需显示处理。

以上都说非检查异常。下面开始检查异常。由于IO结构异常很常见,我们直接来看看它的子类。

套接字异常

通信编程中套接字异常很常见。例如下面的代码

@GetMapping("/socket") public String showSocketException() throws Exception{ ServerSocket socket = new ServerSocket(8081); socket.close(); socket.setReuseAddress(true); return prefix "异常未抛出"; } 一套接口服务端启动,马上关闭。关闭后再调用setReuseAddress。关闭后再调用setReuseAddress。这时候就会抛出java.net.SocketException: Socket is closed。

注意SocketException检查异常,需要显示处理

绑定异常

套接字异常有一种情况,可以清楚地知道是绑定异常,所以不需要抛出套接字异常等模糊异常。

@GetMapping("/binding") public String showBindingException() throws Exception{ ServerSocket socket = new ServerSocket(80); socket.setReuseAddress(true); return prefix "异常未抛出"; }如上,80端口是http自定义通信程序不能使用默认端口。此时将抛出java.net.BindException: Permission denied。此时将抛出java.net.BindException: Permission denied。

注意BindException检查异常,需要显示处理。

主机名未知异常

主机名未知异常,如内网DNS由于机器下线等原因,出现问题或远程调用时找不到主机。构造可以人工连接未启用的端口。

@GetMapping("/unknownHost") public String showUnknownHostException() throws Exception{ new Socket("ttt", 5300); return prefix "异常未抛出"; }注意UnknownHostException检查异常,需要显示处理。

超时异常

超时异常很常见,因为它涉及到程序内部线程和程序之间的通信。具体代码有点长,详见

https://github.com/xiexiaojing/yuna

抛出

java.util.concurrent.TimeoutException。具体代码有点长,详见

https://github.com/xiexiaojing/yuna

抛出

java.util.concurrent.TimeoutException。它是concurrent包里的一类。注意TimeoutException检查异常,需要显示处理。

反射操作异常及其子类

反射操作异常一般只在启动时看到,一般不会发生在线程序操作中。因为它是在常见类中处理的

{n}{n}

  上面可以看到在java.net.InetAddress的源码里,

{n}{n}

  ReflectiveOperationException的处理是直接抛出Error。在程序启动时,经常会由于maven pom里引入的包冲突、版本不合适、或者是缺少包引起「类找不到异常」。例如下面的测试例子:{n}{n}

  @GetMapping("/cl

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时候联系我们修改或删除,多谢。

标签:终于有人把一切都拿走了Java总结了异常处理方法

智聪说说网
  • 本文由 发表于 2023-01-1222:27:12
  • 转载请务必保留本文链接:https://www.zhicongwang.com/90094.html