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:一致性---- ...
随机推荐
- java中string与json互相转化
在Java中socket数据传输时,数据类型往往比較难选择.可能要考虑带宽.跨语言.版本号的兼容等问题. 比較常见的做法有两种:一是把对象包装成JSON字符串传输,二是採用java对象的序列化和反序列 ...
- Light oj 1138 - Trailing Zeroes (III) 【二分查找好题】【 给出N!末尾有连续的Q个0,让你求最小的N】
1138 - Trailing Zeroes (III) PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...
- linux和unix的对照
在之前的博客中说到,linux是一个单一内核的操作系统,但它与传统的单一内核UNIX操作系统不同. 在普通单一内核系统中,全部内核代码都是被静态编译和链接的. 而在linux中,能够动态的装入和卸载内 ...
- Lesson 2 Building your first web page: Part 1
In this ‘hands-on’ module we will be building our first web page in no time. We just need to quickly ...
- springboot 使用mybatis 通用Mapper,pagehelper
首先需要maven导入需要的包,这里用的是sqlserver,druid,jtds连接数据库 <dependency> <groupId>com.alibaba</gro ...
- POJ 3276 枚举+差分?
题意: 思路: 先枚举一下k 贪心:如果当前是B那么就翻 差分一下序列 mod2 就OK了 //By SiriusRen #include <cstdio> #include <cs ...
- Lambda表达式相当于一个函数
看来你对Lambda完全不懂.Lambda表达式相当于一个函数. 比如model => model.Name相当于string 一个函数(Model的类型 model) { return ...
- [Chromium文档转载,第004章]Mojo Synchronous Calls
For Developers > Design Documents > Mojo > Synchronous Calls Think carefully before ...
- Ubuntu16.04添加HP Laserjet Pro M128fn打印机和驱动
一.全部设置->打印机->添加新打印机 添加打印机 二.选择自动搜索到的网络打印机HP Laserjet Pro M128fn,点击添加. 三.添加打印机完成,打印测试页进行测试. 四. ...
- 前台ajax验证技术采用正则表达式
var flag1,flag2,flag3,flag4,flag5,flag6=false; function val(obj) { var regBox = { /* regEmail : /^([ ...