有没有异常处理翻车过的,绩效还被打了C
絮叨
因为程序异常处理问题,就在前几天龙叔的服务挂了几秒钟。

完了,马上季度末打绩效,竟然在这里翻车了,心如刀绞啊。
虽然没有影响到用户体验,但是找到问题并解决掉问题是工程师日常追求之一。
作为一个优秀的工程师,应该还得加几点:
- 弄清问题本质
- 总结问题原因
- 举一反三,防止出现类似错误
异常处理,对于每个开发者来说一点不陌生。
有人这样描述,“一个开发者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
这些都是非常常见的异常,当然还有一些其他异常,大家要在日常工作中及时总结,写到你的小本本上。
今天的内容就到这里了,有帮助记得点个赞。
我是龙叔,我们下期见️。
有没有异常处理翻车过的,绩效还被打了C的更多相关文章
- C++异常处理:try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- C++异常处理: try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- Windows异常处理机制简介
windows系统里,为了保证系统内核的强壮和稳定,为了保证用户程序的强壮和稳定,提供了异常处理机制,来帮助程序员和系统使用人员处理异常.简单来说,当CPU执行代码时,发生异常,会把异常告知操作系统, ...
- 【VS开发】C++异常处理操作
异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使用过异常,但是你会是一种习惯吗,不要老是想着当我打开一个文件的时候才用异常判断一下,我知道对你来说你喜欢用re ...
- Reactor详解之:异常处理
目录 简介 Reactor的异常一般处理方法 各种异常处理方式详解 Static Fallback Value Fallback Method Dynamic Fallback Value Catch ...
- springboot优雅的异常处理
springboot全局异常处理 @ControllerAdvice 尽管springboot会对一些异常进行处理,不过对于开发者来说,这还不太便于维护,因此我们需要自己来对异常进行统一的捕获与处理. ...
- 13、零配置Struts2开发
Convention 插件 从 Struts 2.1 开始, Struts 可以使用 Convention 插件来支持零配置: Convention 插件完全抛弃配置信息, 不仅不需要使用 strut ...
- 10个关于Java异常的常见问题
这篇文章总结了十个经常被问到的JAVA异常问题: 1.检查型异常VS非检查型异常 简单的说,检查型异常是指需要在方法中自己捕获异常处理或者声明抛出异常由调用者去捕获处理: 非检查型异常指那些不能解决的 ...
- 20145102 《Java程序设计》第5周学习总结
20145102 <Java程序设计>第5周学习总结 教材学习内容总结 数组在内存中会是连续的线性空间,根据索引随机取回时速度快,如果操作上有这类需求时,像是排序,就可以使用;ArrayL ...
随机推荐
- 算法-搜索(6)B树
B树是平衡的m路搜索树. 根结点至少两个子女,根结点以外的非失败结点至少⌈m/2⌉个子女,所有失败结点都在h+1层. 第h层至少2⌈m/2⌉h-1个结点,因此失败结点数n+1≥2⌈m/2⌉h-1个. ...
- 【转】python调用youtube-dl实现视频下载
youtube-dl是一个命令行程序,用于从YouTube.com和更多网站下载视频.它需要Python解释器,版本2.6,2.7或3.2+,并且支持Unix,Windows或Mac OS X中运行. ...
- JAVA指令集——GETSTATIC
(indexbyte1<<8)|indexbyte2——得到index 1,从runtimeconstantpool中取得index处的FieldRef,FieldRef已经解析完成 Fi ...
- 力扣Leetcode 983. 最低票价
最低票价 在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行.在接下来的一年里,你要旅行的日子将以一个名为 days 的数组给出.每一项是一个从 1 到 365 的整数. 火车票有三种不同的销 ...
- Mono嵌入C++
http://docs.go-mono.com/index.aspx?link=xhtml%3Adeploy%2Fmono-api-embedding.html https://www.mono-pr ...
- FZU - 2038 -E - Another Postman Problem (思维+递归+回溯)
Chinese Postman Problem is a very famous hard problem in graph theory. The problem is to find a shor ...
- python-opencv 图像捕捉多个不规则轮廓,与轮廓内接区域(圆/矩形)思路-持续更新编辑中(会附上详细的思路解释和图片)
整体思路: 1.原图灰度化 2.灰度图截取mask区域 3.mask区域二值化 4.二值化图像运算(开运算) 5.原灰图轮廓提取 6.不规则轮廓校准(外接矩形/内接矩形) 注:代码依次头尾连接哦! 0 ...
- python简介以及简单代码——python学习笔记(一)
学习来源:https://www.liaoxuefeng.com/wiki/1016959663602400 了解python 简单编写并实现python代码 命令行模式和python交互模式 了解p ...
- C014:不用算术分割显示逆序三位数
程序: #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { int handred,ten,ge; do{ pri ...
- leetcode刷题-69x的平方根
题目 实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4输出: 2 思 ...