Catch Me If You ... Can't Do Otherwise--转载
原文地址:https://dzone.com/articles/catch-me-if-you-cant-do-otherwise
I don't know whether it's an anti-pattern or just a common and very popular mistake, but I see it everywhere and simply must write about it. I'm talking about exception catching without re-throwing. I'm talking about something like this Java code:
try {
stream.write(data);
} catch (IOException ex) {
ex.printStackTrace();
}

©Catch Me If You Can (2002) by Steven Spielberg
Pay attention: I don't have anything against this code:
try {
stream.write('X');
} catch (IOException ex) {
throw new IllegalStateException(ex);
}
This is called exception chaining and is a perfectly valid construct.
So what is wrong with catching an exception and logging it? Let's try to look at the bigger picture first. We're talking about object-oriented programming — this means we're dealing with objects. Here is how an object (its class, to be exact) would look:
final class Wire {
private final OutputStream stream;
Wire(final OutputStream stm) {
this.stream = stm;
}
public void send(final int data) {
try {
this.stream.write(x);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Here is how I'm using this class:
new Wire(stream).send(1);
Looks nice, right? I don't need to worry about that IOException when I'm calling send(1). It will be handled internally, and if it occurs, the stacktrace will be logged. But this is a totally wrong way of thinking, and it's inherited from languages without exceptions, like C.
Exceptions were invented to simplify our design by moving the entire error handling code away from the main logic. Moreover, we're not just moving it away but also concentrating it in one place — in themain() method, the entry point of the entire app.
The primary purpose of an exception is to collect as much information as possible about the error and float it up to the highest level, where the user is capable of doing something about it. Exception chaining helps even further by allowing us to extend that information on its way up. We are basically putting our bubble (the exception) into a bigger bubble every time we catch it and re-throw. When it hits the surface, there are many bubbles, each remaining inside another like a Russian doll. The original exception is the smallest bubble.
When you catch an exception without re-throwing it, you basically pop the bubble. Everything inside it, including the original exception and all other bubbles with the information inside them, are in your hands. You don't let me see them. You use them somehow, but I don't know how. You're doing something behind the scenes, hiding potentially important information.
If you're hiding that from me, I can't promise my user that I will be honest with him and openly report a problem when it occurs. I simply can't trust your send() method anymore, and my user will not trust me.
By catching exceptions without re-throwing them, you're basically breaking the chain of trust between objects.
My suggestion is to catch exceptions as seldomly as possible, and every time you catch them, re-throw.
Unfortunately, the design of Java goes against this principle in many places. For example, Java has checked and un-checked exceptions, while there should only be checked ones in my opinion (the ones you must catch or declare as throwable). Also, Java allows multiple exception types to be declared as throwable in a single method — yet another mistake; stick to declaring just one type. Also, there is a generic Exception class at the top of the hierarchy, which is also wrong in my opinion. Besides that, some built-in classes don't allow any checked exceptions to be thrown, like Runnable.run(). There are many other problems with exceptions in Java.
But try to keep this principle in mind and your code will be cleaner: catch only if you have no other choice.
P.S. Here is how the class should look:
final class Wire {
private final OutputStream stream;
Wire(final OutputStream stm) {
this.stream = stm;
}
public void send(final int data)
throws IOException {
this.stream.write(x);
}
}
Catch Me If You ... Can't Do Otherwise--转载的更多相关文章
- UDPClient的用法
UDP_Server: UdpClient receivingUdpClient = ); IPEndPoint RemoteIpEndPoint = ); try { byte[] sdata = ...
- Java编程思想学习(九) 异常处理
java的异常处理机制可以使程序有极好的容错性,让程序更加的健壮.所谓的异常,就是指的阻止当前方法或作用域继续执行的问题,,当程序运行时出现异常时,系统就会自动生成一个Exception对象来通知程序 ...
- C#中DataTable与实体集合通用转换(使用扩展方法)
本案例提供了:把DataRow转换为单个实体.dataTable转换为List泛型支持时间格式转换. 下文的方法都是扩展方法.扩展方法要求写在静态类中,方法也要静态. 它必须在一个非嵌套.非泛型的静态 ...
- Android Studio经常使用操作技巧(不断更新)
这段时间一直在用Android Studio做一些Demo的开发.一開始从Eclipse中转向这个开发工具,各种不适应,希望此博文能够一直更新.还有网友能够分享出自己方便更好更快开发的一些技巧. 首先 ...
- jdbc批量插入
分享牛,分享牛原创.有这样一个需求,文本文件中的数据批量的插入mysql,怎么用jdbc方式批量插入呢? jdbc默认提供了批量插入的方法,可能用一次就忘记了,这里做笔记记录一下jdbc批量插入吧. ...
- Java IO流学习总结四:缓冲流-BufferedReader、BufferedWriter
在上一篇文章中Java IO流学习总结三:缓冲流-BufferedInputStream.BufferedOutputStream介绍了缓冲流中的字节流,而这一篇着重介绍缓冲流中字符流Buffered ...
- C# p2p UDP穿越NAT,UDP打洞源码
思路如下(参照源代码): 1. frmServer启动两个网络侦听,主连接侦听,协助打洞的侦听. 2. frmClientA和frmClientB分别与frmServer的主连接保持联系. 3. 当f ...
- Spring 事物传播特性
Spring 事物传播特性 这是Spring官方的定义 一共有7种 摘自源码省略了一部分 public interface TransactionDefinition { int PROPAGATIO ...
- java当中JDBC当中请给出一个Oracle DataSource and SingleTon例子
[学习笔记] 6.Oracle DataSource and SingleTon: import oracle.jdbc.pool.OracleDataSource;import java.sql.C ...
- SQL数据库—<7>事务、异常和游标
事务 一.什么是事务能够保证数据的一致性的代码控制,要么执行提交,要么滚回事务的初始状态 二.事务的四大特性:ACIDA:原子性-------事务不可拆开,要么执行要么回滚无中间状态C:一致性---- ...
随机推荐
- ArcGIS api for javascript——图形-使用多个图形图层
描述 本例展示了如何增加多个图形图层到地图.一个图形图层显示国家,另一个显示城市.在一个地图中有多个图形图层的能力是在ArcGIS JavaScript API v1.4增加的. 从蓝色的城市点分隔灰 ...
- 局部特化 & 特化
注意,显式特化不是一个模板.如果是类型跟显式特化一样,那么不是实例化. 显式特化类的函数,不需要再加template,因为不是模板方法. 特化类的函数跟模板类不一定要一样,但是一样更好. 不支持局部特 ...
- Vue进阶之事件处理器
过滤 <html> <head> <meta charset="UTF-8"> <meta name="viewport&quo ...
- Android开发之蓝牙(Bluetooth)操作(二)--修改本机蓝牙设备的可见性,并扫描周围可用的蓝牙设备
版权声明:本文为博主原创文章,未经博主允许不得转载. 一. 修改本机蓝牙设备的可见性 二. 扫描周围可用的蓝牙设备 Eg: 一. 清单文件AdroidManifest.xml: <?xml v ...
- ACM的算法分类 2015-04-16 14:25 22人阅读 评论(0) 收藏
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. ...
- 配置CiscoWorks 2000 ANI同步
配置CiscoWorks 2000 ANI同步 在CiscoWorks 2000的LAN ManagementSolution(LMS)中,Cisco包含了一种ANI的自动发现过程和Res ...
- 遇到的兼容性bug
1.(IE6):ie6环境下,通过设置z-index:999:无效果: 原因:IE6下,决定层级高低的不是当前的父标签,而是整个DOM tree(节点树)的第一个relative属性的父标签. 解决办 ...
- oracle基础入门(一)
一:Oracle的安装 我所知的Oracle的数据库有 10g,11g, 12g, 我们常用的是10g ,因为10g有scott的用户,而11和12现在还没有(哪位大神看到有问题可以指出哦), ...
- 关于bootstrap IE8的兼容性问题
非常久没有写技术类的文章了.这几天在用bootstrap来做我们站点的UI框架,感觉还是不错的.只是遇到一点不大不小的问题,那就是有朋友在IE8下訪问我们的站点.界面变成了跟手机浏览一样的界面. 后来 ...
- Python!Are you kidding me?
前几天由于python给我带来了兴奋写了一篇文章叫做<The beauty of python 1>,今天则是由于一个小错误而写下此文. 也是缘因为我的工作,问题是这种: 我有一个文档.里 ...