Atitit 反模式 黑名单 异常处理 反模式(antipatterns) 目录 1.1. 记录并抛出(log and throw) 1 1.2. 抛出异常基类(Throwing Excepti
Atitit 反模式 黑名单 异常处理
反模式(antipatterns)
目录
1.1. 记录并抛出(log and throw) 1
1.2. 抛出异常基类(Throwing Exception) 2
1.3. Throwing the Kitchen Sink(太多性质类似的异常 太细节化) 2
1.4. 捕获异常基类(Catching Exception) 2
1.5. 破坏性的包装 丢失异常链 2
1.6. 记录并抛出Null(Log and Return Null) 3
1.7. 捕获然后忽略(Catch and Ignore) 3
1.8. 在finally中抛出异常 3
1.9. 一条消息分多行进行记录(Multi-Line Log Messages) 4
1.10. 本应抛出UnsupportedOperation异常却抛出null(Unsupported Operation Returning Null) 4
1.11. 忽略InterruptedException (Ignoring InterruptedException ) 4
1.12. 依靠getCause()函数(Relying on getCause()) 5
- 记录并抛出(log and throw)
例如
catch (NoSuchMethodException e) { |
或者
catch (NoSuchMethodException e) { |
或者
catch (NoSuchMethodException e) { |
这三种方式都是错误的。这类方式是最讨人厌的错误处理反模式。要么记录一个异常,要么抛出一个异常,但不要同时进行“抛出”和“记录”两种操作。同时进行这两类操作会对同一个问题产生多种log消息,这会给运维人员分析日志带来麻烦。
- 抛出异常基类(Throwing Exception)
看下面这个例子:
public void foo() throws Exception {
这样做是草率的,它完全违背了使用checked异常的目的。它告诉调用你代码的人“您现在调用的函数可能会出错哦”,虽然这有一些作用的,但千万别这么做。应该准确声明你的方法有可能会抛出的异常的类型。如果要抛出的异常有很多种,那么可以将它们包装到你定义的自定义异常中。(详见下文的"Throwing the Kitchen Sink")
- Throwing the Kitchen Sink(太多性质类似的异常 太细节化)
例如:
public void foo() throws MyException, |
抛出多个checked类型的异常是可以的,只要函数调用者能针对不同的异常提供不同的处理方法即可。如果你抛出的几个checked异常对调用者而已差不多是同样的性质,那么应该将它们包装成一类单独的checked异常。
- 捕获异常基类(Catching Exception)
例如:
try { |
这通常是错误的和草率的。这种方式下捕获了原本应该被抛出的异常。捕获异常基类的问题在于,如果你随后要调用别的函数,而这个函数含有一个checked类型的异常(函数开发者希望你处理这个特定的checked异常),那么由于你之间捕获了Exception基类(甚至是Throwable类),那么你或许永远不知道你的代码里有本应该处理但却没有处理异常,这样一来你的代码是错误的而你却无从知晓(IDE不会提示,因为Exception基类被捕获了)。
- 破坏性的包装 丢失异常链
例子:
catch (NoSuchMethodException e) { |
这种方式破坏了原本的异常对象e的追踪堆栈,使用这种包装方式你将无法追踪这个异常之前的传递路径。
- 记录并抛出Null(Log and Return Null)
例子:
catch (NoSuchMethodException e) { |
或
catch (NoSuchMethodException e) { |
并不是所有情况下这样处理都是错的,但通常它是不正确的处理方式。相比于返回null,抛出异常让该函数的调用者来处理会更好一些。只有在正常的情况下(非异常处理)才应该有返回null这样的语句出现。例如,当查找的字串不存在时返回null。
- 捕获然后忽略(Catch and Ignore)
例子:
catch (NoSuchMethodException e) { |
这种方式是阴险的,它不但不做任何处理而是返回null,并且还吞掉了原本的异常对象,使它丧失了所有的信息!!
- 在finally中抛出异常
例子:
try { |
如果 cleanUp()不会抛出任何异常,那么这样写是没问题的。在上例中,如果blah()函数抛出了一个异常,然后在finally 语句块中cleanUp()又抛出一个异常,那么第二个异常将会被抛出,而第一个异常则完全消失了。如果finally 语句块中调用的函数会抛出异常,那么要么处理它,要么记录它,千万不要让它逃出finally 语句块的范围。
- 一条消息分多行进行记录(Multi-Line Log Messages)
例子:
LOG.debug("Using cache policy A"); |
不管在那个代码层次上,都应该尝试将消息组织到一起,对于上面这个例子,正确的编码方式是:
LOG.debug("Using cache policy A, using retry policy B");
将统一组的日志记录到两个调用语句中,在测试用例的测试下或许看起来没什么问题。但是在多线程(假设有500个线程)的系统中,信息将喷涌般地被记录到log文件中,而讲一条语句拆做两条写可能会让这两条语句中间相差十万八千里,而它们本应该同时输出的。
- 本应抛出UnsupportedOperation异常却抛出null(Unsupported Operation Returning Null)
例子:
public String foo() { |
如果上述代码是用在一个抽象基类中,用来提供钩子(hooks)以供子类在重写的话,那么是可以的。若非如此,则应该抛出一个UnsupportedOperationException 而不是返回一个null。对于方法的调用者而已,如果你抛出了一个UnsupportedOperationException,那么他们会更容易知道自己的方法为什么没有正常工作。如果你是抛出null的话,函数的调用者可能就会接收到莫名其妙的NullPointerException了。
- 忽略InterruptedException (Ignoring InterruptedException )
例子:
while (true) { |
InterruptedException 是一个提示,用来告知代码不管现在在做什么,都停下。一个线程被中断的情况通常出现在事务处理时间耗尽或线程池被关闭。相比于忽略InterruptedException,代码中更应该做的是赶快完成现在在做的工作,并结束当前线程。所以,正确的写法应该是:
while (true) { |
- 依靠getCause()函数(Relying on getCause())
例子:
catch (MyException e) { |
依赖于getCause()函数的结果会让你的代码变得脆弱。如果你调用的函数或者你所依赖的代码改变了它的底层实现,换了一种异常封装,而你却依赖之前的异常类型来进行判断,怎么办?其实你本意上是想判断这个异常最初的根源是什么,也就是cause's cause。现在Apache的 commons-lang提供了一个ExceptionUtils.getRootCause() 方法来轻松获得异常源。
结论
好的异常处理是搭建具有鲁棒性和可靠性系统的关键。避免出现上文中提出的反模式可以帮助你搭建一个可维护的、可适应变化的,且能与其他系统共同和谐工作的系统。
Atitit 反模式 黑名单 异常处理 反模式(antipatterns) 目录 1.1. 记录并抛出(log and throw) 1 1.2. 抛出异常基类(Throwing Excepti相关推荐
- java 如何捕获线程中的异常处理_如何捕获Java中另一个线程抛出的异常?
参见英文答案 > How to catch an Exception from a thread 14个 我正在使用一个创建 ...
- 半同步/半异步模式和领导者/追随者模式
这两种都是高效的并发模式. 半同步半异步模式: 出现原因: 异步线程执行效率高,但是编写复杂,同步线程效率低,但是逻辑简单.服务器要求好的实时性和同时处理多用户的请求,英雌采用两者结合的形式. 具体情 ...
- 重构是提高可测试性的主要手段 《设计模式》《代码重构》《从重构到模式》 《反模式》 重构时机 编写测试时候 修改BUG时候
l重构是提高可测试性的主要手段 <设计模式><代码重构><从重构到模式> <反模式> 重构时机 编写测试时候 修改BUG时候
- 多线程编程反模式_编程反模式
多线程编程反模式 您是否曾经进行过代码审查,记录了非常高的WTF / m? 您是否想知道所有这些错误代码的原因是什么? 在大多数情况下,导致原因1的原因是使用设计和编码反模式. 如果您喜欢定义,请参见 ...
- mysql 说说反模式设计_sql反模式分析1
第二章:乱穿马路 2.1 目标:存储多值属性 2.2 反模式:格式化的逗号分隔列表 模糊匹配无法使用索引,影响性能:多表关联麻烦,却极大影响性能:执行聚合查询不方便开发和调试:更新某个字段值必须执 ...
- java图片颜色取反色,照片底片模式
全栈工程师开发手册 (作者:栾鹏) java教程全解 java图片颜色取反色,照片底片模式 测试代码 public static void main(String[] args) {//文件与Buff ...
- Atitit 图像处理类库安装与安装模式的前世今生与未来大趋势attilax总结.docx
Atitit 图像处理类库安装与安装模式的前世今生与未来大趋势attilax总结.docx 1. 安装的原理,主要是解压,复制,设置三大步1 2. 目前我们常见的三大种安装模式,二进制模式与源码安装模 ...
- 黑名单(诸如反爬虫等)
原文链接 引言 正在午睡,突然收到线上疯狂报警的邮件,查看这个邮件发现这个报警的应用最近半个月都没有发布,应该不至于会有报警,但是还是打开邮件通过监控发现是由于某个接口某个接口流量暴增,CPU暴涨.为 ...
- atitit 方便搜索的文档文章结构框架.docx 目录 1.1. 三种搜索模式 tree hash关键词模式 关联搜索,对应的三种索引 1 1.2. 好的标题规范与副标题 1 1.3. Tr
atitit 方便搜索的文档文章结构框架.docx 目录 1.1. 三种搜索模式 tree hash关键词模式 关联搜索,对应的三种索引 1 1.2. 好的标题规范与副标题 1 1.3. Tre ...
- 《JAVA与模式》之模板模式(转载)
模板方法在servlet中的应用:http://www.cnblogs.com/java-my-life/archive/2012/05/14/2495235.html 原文出处:http://blo ...
最新文章
- 一个web.Config或app.Config自定义段configSections的示例
- 提高ADO性能的优秀经验
- Python函数式编程简介(五)偏函数
- 【华为云技术分享】Linux内核模块依赖图绘制(2)
- ChengDu University Mental Health Test 需求分析文档
- win10壁纸不能幻灯片放映_如何设置Win10桌面壁纸幻灯片放映? 设置Win10桌面壁纸幻灯片放映的方法...
- 网易云音乐会员下载正常音乐格式
- (转载)c++builder/delphi中透明panel及透明窗口的实现方法_delphi教程
- hspice 2019 安装流程
- 在龙芯3A3000上安装Debian 10
- matplotlib工具栏源码探析一(禁用工具栏、默认工具栏和工具栏管理器三种模式的差异)
- 趣店PHP面经_腾讯助理PHP开发工程师外包岗面经
- element时间日期选择器组件设置默认时间
- Unity发布WebGL不显示中文字体问题
- 港联证券|TMT板块全线退潮,这些个股获主力逆市抢筹
- cad2006安装未找到html文件,我的CAD已安装在D驱动器上,但是在打开dwg文件时,它提示找不到C...
- GraphSAGE: 算法原理,实现和应用
- 【操作系统】保姆级教程(VMware)Ubuntu+qemu+xv6安装调试
- Epson L4158打印机安装与配置
- php操作数据库的五个步骤,请写出PHP操作数据库的五个步骤
热门文章
- c++ 中 try catch throw异常
- html5 video mute按钮,How to mute an html5 video player
- php的原子操作,php实现含有redis命令的原子操作
- sci的figure怎么做_一文看懂SCI论文中都有哪几种Figure
- python最简单的爬取邮箱地址怎么写_详解python定时简单爬取网页新闻存入数据库并发送邮件...
- COOKIE和SESSION之间的区别以及用法
- Golang让协程交替输出
- 在微软Ajax框架中异步调用WebService(JavaiScript中调用)
- 关于wordpress主题只显示一个的解决办法
- 安卓飞机大战(六) 动态Gif图的添加