絮叨

因为程序异常处理问题,就在前几天龙叔的服务挂了几秒钟。

完了,马上季度末打绩效,竟然在这里翻车了,心如刀绞啊。

虽然没有影响到用户体验,但是找到问题并解决掉问题是工程师日常追求之一。

作为一个优秀的工程师,应该还得加几点:

  • 弄清问题本质
  • 总结问题原因
  • 举一反三,防止出现类似错误

异常处理,对于每个开发者来说一点不陌生。

有人这样描述,“一个开发者90%的时间都是在处理程序异常”。

这样说也不算是什么过错,毕竟正常的逻辑总是轻松容易的写完,异常处理往往会占据开发者大多数时间。

既然这么占据我们的开发时间,何不主动花点时间去了解他熟悉他,切莫让他成为了最熟悉的陌生人。

文章大纲

异常分类

在Java中,异常分为受检查的异常,与运行时异常。两者都在异常类层次结构中。下面的图展示了Java异常类的继承关系。

不难看出所有的异常都继承自一个共同的父类Throwable,而Throwable有两个重要的子类:Exception(异常)和Error(错误)。

Error(错误)

工程师最怕的就是Error,看到error和fail头都大了三圈,感觉Error总是和我过不去。

Error是指Java 运行时系统的内部错误和资源耗尽错误。

应用程序不应该抛出这种类型的对象。

如果出现了这样的内部错误, 除了通告给用户,并尽力使程序安全地终止之外, 再也无能为力了。一般这种情况很少出现。

这种错误会导致你的程序日常运行着,突然某天就夭折了。

Exception(异常)

异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。

异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。

Java通过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的错误条件

当条件生成时,错误将引发异常。

异常和错误的区别:异常能被程序本身处理,错误是无法处理。

异常主要分为运行期异常非运行期异常(编译异常)

运行期异常很好理解,就是程序跑着跑着因为触发某个条件,导致异常发生了。比如越界了,NullPointerException等等。

编译期异常,就是程序编译时抛出的异常,比如访问的文件不存在。这类异常很好避免,编译不会通过,不解决掉,程序就没法运行起来。

当然有人也把异常分为可查异常不可查异常

可查异常 也称之为编译器要求必须处理的异常,一般编译器都会检查他,出现这类异常要么用捕获他,要么抛出他,总之必须处理他。

不可查异常 编译器没法检查的,必须靠程序员去主动检查,然后处理掉他。

分类的方法不是很重要,怎样分取决于你处于某种情况下,最终都是要明白这些异常,并处理它。

异常处理机制

上面基本都明白了java异常是什么,以及有哪些异常,下面我们就来聊聊用什么样的机制去处理这些异常。

八字方针 抛出异常,捕捉异常

throw 语句用于拋出异常,throws 语句用于声明可能会出现的异常。

举个例子:

 public  Integer division(int x, int y) {if (y == 0)throw new ArithmeticException("抛出算术异常"); //抛出异常return x / y;}

throws抛出异常的规则:

  1. 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。

2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现受可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误

3)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。

4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。

java采用try-catch-finally语句来对异常进行捕获并处理。

try{//可能产生异常的代码
}catch (Exception e){//异常处理逻辑
}
try{//可能产生异常的代码
}catch (Exception e){//异常处理逻辑
}finally {//必须执行的逻辑
}

这语法大家应该在熟悉不过了,算了,龙叔还是啰嗦一遍。

try语句块:该语句块中是程序正常情况下应该要完成的功能,而这些代码中可能会产生异常,其后面的catch语句块就是用来捕获并处理这些异常的。

catch语句块:该语句块用来捕获并处理try语句块中产生的异常。

每个catch语句块声明其能处理的一种特定类型的异常,catch后面的括号中就是该特定类型的异常。

在Java7以前,每个catch语句块只能捕获一种异常,从Java7开始就支持一个catch捕获多种异常,多个异常之间用|隔开。

try{//可能会产生异常的代码}catch(Exception1 | Exception2 |... | Exception_n e1){//统一处理的异常代码}finally{//通常是释放资源的代码}

finally块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。

在以下4种特殊情况下,finally块不会被执行:

1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。

try、catch、finally语句块的执行顺序:

到这里大家基本明白了异常怎么来的,怎么处理的,接下来说一个常见的异常屏蔽问题

一般情况下都是try中进行捕捉可能出现的异常,catch对异常进行处理,finally中进行一些资源关闭工作。

正常情况倒也没啥说的,但咋就怕异常情况啊。

举个例子:

try{//可能会产生异常的代码}catch(Exception1 | Exception2 |... | Exception_n e1){//统一处理的异常代码}finally{//通常是释放资源的代码in.close();out.close();}

是不是日常都这么写,看起来蛮正常的。

如果我们的finally语句块中也抛出异常,会怎么办?

    public Integer division(int x, int y) throws Exception {try{return x/y;}catch (ArithmeticException e){System.out.println(e.getMessage());throw new ArithmeticException("算术异常");}finally {System.out.println("释放资源");throw new Exception("释放资源异常");}}

例如这段代码,本意是想抛出算术运算异常 ,结果抛出了释放资源异常

由于异常信息的丢失,异常屏蔽可能会导致某些bug变得极其难以发现,会让你加班加到心态崩溃的。

这就是屏蔽异常,如何解决这种屏蔽异常?

有人看了上面的代码,又发现了另一个问题。try中有return语句,finally语句还会不会执行?

这个问题很好,答案是会执行,并且在方法返回调用者前执行

解决屏蔽异常问题

Java 1.7中新增的try-with-resource语法糖来很好的解决这种因为关闭资源引起的异常屏蔽问题。

 public void testExcep(){BufferedInputStream in = null;BufferedOutputStream out = null;try {in = new BufferedInputStream(new FileInputStream(new File("in.txt")));out = new BufferedOutputStream(new FileOutputStream(new File("out.txt")));} catch (IOException e) {e.printStackTrace();} finally {try {if (in != null) {in.close();}if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();}}}

为了释放资源,我们不得不这样写。但当我们熟悉try-with-resource语法,我们可以这样写。

public static void main(String[] args) {try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File("in.txt")));BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {//处理输入数据并输出} catch (IOException e) {//捕捉异常并处理}}

在try子句中能创建一个资源对象,当程序的执行完try-catch之后,运行环境自动关闭资源。

代码写起来简洁,也会解决掉屏蔽异常问题

当然也要注意,在使用try-with-resource的过程中,一定需要了解资源的close方法内部的实现逻辑。否则还是可能会导致资源泄露。

怎么样,是不是很简单呢?学会了我们一起去装逼

常见异常问题

算术异常类:ArithmeticExecption

空指针异常类:NullPointerException

类型强制转换异常:ClassCastException

数组负下标异常:NegativeArrayException

数组下标越界异常:ArrayIndexOutOfBoundsException

文件已结束异常:EOFException

文件未找到异常:FileNotFoundException

字符串转换为数字异常:NumberFormatException

操作数据库异常:SQLException

输入输出异常:IOException

方法未找到异常:NoSuchMethodException

这些都是非常常见的异常,当然还有一些其他异常,大家要在日常工作中及时总结,写到你的小本本上。

今天的内容就到这里了,有帮助记得点个赞

做好异常处理,防止无故翻车相关推荐

  1. 【学习笔记】JAVA基础——异常处理部分

    文章目录 前言 简介 一. try.catch与finally ① try && catch ② finally ③ throws 补充:JVM 相关 二. 异常的分类 ① 分类解释与 ...

  2. 完善你的Laravel异常处理

    异常处理是编程中十分重要但也最容易被人忽视的语言特性,它为开发者提供了处理程序运行时错误的机制,对于程序设计来说正确的异常处理能够防止泄露程序自身细节给用户,给开发者提供完整的错误回溯堆栈,同时也能提 ...

  3. Laravel核心解读--异常处理

    异常处理是编程中十分重要但也最容易被人忽视的语言特性,它为开发者提供了处理程序运行时错误的机制,对于程序设计来说正确的异常处理能够防止泄露程序自身细节给用户,给开发者提供完整的错误回溯堆栈,同时也能提 ...

  4. C++ Qt全局异常处理器_异常处理

    异常处理是编程中十分重要但也最容易被人忽视的语言特性,它为开发者提供了处理程序运行时错误的机制,对于程序设计来说正确的异常处理能够防止泄露程序自身细节给用户,给开发者提供完整的错误回溯堆栈,同时也能提 ...

  5. 16. 设计模式之契约原则:如何做好 API 接口设计?

    一.契约式设计原则:API 设计的指导书 无论是架构设计还是编码实现,现在都越来越离不开接口设计,接口可以说是新时代的"集装箱",是得到了几乎所有人一致共识的通用标准. GoF 在 ...

  6. PHP加密时遇到try错误,深入学习PHP错误与异常处理

    一.PHP异常处理机制 由于我的工作岗位性质,我绝大部分的开发工作涉及到的操作风险都非常高,而且很频繁地使用其他部门提供的接口.所以,对于程序中可能出现的异常和错误都要有相应的处理方法,否则遗漏的话会 ...

  7. 2004-10-26+ 用户输入的安全问题

    最近在看一本叫<asp.net安全性高级编程>,把一些感兴趣的东西写成笔记当到这里吧,今天这一篇主要是讲怎么防御注入攻击的. script injection 1.验证内容 a.使用reg ...

  8. java程序实现按并发数收费_java-实战java高并发程序设计-ch3JDK并发包

    JDK 并发包 3.1 多线程的同步协助:同步控制 3.1.1 synchronized 扩展功能:重入锁 jdk1.5之前重入锁ReentrantLook性能好于synchronized, 但jdk ...

  9. 有了这篇 Shell 脚本实践指南,同事对我“刮目相看”!

    前言 由于工作需要,最近重新开始拾掇shell脚本.虽然绝大部分命令自己平时也经常使用,但是在写成脚本的时候总觉得写的很难看.而且当我在看其他人写的脚本的时候,总觉得难以阅读.毕竟shell脚本这个东 ...

最新文章

  1. java iterator对象_JAVA Iterator 详解 代码
  2. python画柱形图-Python绘制精美图表之双柱形图
  3. Camelot:从pdf中提取表格数据
  4. 区块链BaaS云服务(38)点存DCpool分布式存储
  5. 自媒体运营要知道的哪些知识
  6. 通信系统概论_移动通信复习资料
  7. Zabbix4.0 for PostgreSQL (上篇):基础环境的搭建部署
  8. 2021-09-211547G - How Many Paths?
  9. Spring Boot 面试题
  10. 斗地主AI算法——第四章の权值定义
  11. springmvc 全局编码_Java SpringMVC乱码问题排查和解决
  12. HTML input 控件
  13. 思科刀片服务器系统,思科 UCS B 系列刀片服务器
  14. Local Binary Patterns LBP算法
  15. 双因素方差分析 matlab,MATLAB的双因素有交互效应的方差分析
  16. item_get - 获得搜好货商品详情
  17. apple 的 app id
  18. 机器学习模型评估与改进:网格化调参(grid search)
  19. 计算机网络安全控制技术
  20. 在元宇宙的概念之下,互联网与数字经济不再是水火不容的存在

热门文章

  1. java习题4.1-将学生的学习成绩按不同的分数段分为优、良、中、及格和不及格五个登记,从键盘上输入一个0~100的成绩,输出相应的等级。要求用switch语句实现
  2. 本地ecshop网站怎么上传到服务器,ecshop 上传服务器
  3. 【深度学习】3-从模型到学习的思路整理
  4. 2022“杭电杯”中国大学生算法设计超级联赛(7)
  5. 【黑帽大牛】浅谈SEO快排系统对网站排名优化真的有帮助吗?【精品】
  6. TF:TF定义两个变量相乘之placeholder先hold类似变量+feed_dict最后外界传入值
  7. 学生机房随堂测试软件,全智能考试系统——随堂评测考试系统
  8. 杂事记诗-- 读网文《穷鬼的上下两千年》有感
  9. 贫民窟的hadoop日志---hadoop基本搭建
  10. Microsoft Windows-关于“sfc/scannow”(立即扫描所有受保护的系统文件的命令)的一些问题