Java 异常处理


相信了解 Java 的人对于通过 try-catch-finally 来处理异常应该都有所了解了。但可能很多人在实际中还只是仅仅将代码包起来,然后在 catch 中输出错误信息而已,但是 Java 的异常处理其实也有很多要注意的地方。

基础

Java 中的异常处理都是围绕着 try-catch-finally, throw, throws 这几个展开的,也就是:

  • try-catch-finally:捕获异常并处理。
  • throw:遇到错误的时候抛出一个异常。
  • throws:声明一个方法可能抛出的异常(所有可能抛出的异常都需要声明)。

Java 中的异常分为 checked exception 和 unchecked exception。

java.lang.RuntimeException 和 java.lang.Error 类及其子类是 unchecked exception,其余的就是 checked exception 了。

当你在进行 API 设计时,必须要知道异常声明也是 API 的一部分。如果你为你公开的 API 声明了可能抛出的异常,在今后很长的一段时间里你可能都很难甩掉它们了。

今后如果你要重构或进一步开发这些 API 时,就不得不考虑这些异常带来的向后兼容性问题。因为,如果你在日后的版本中删除了某个异常的声明,就会造成之前用户的代码无法通过编译。

仔细考虑你要声明抛出的异常。

异常处理

异常处理的难点主要是对于什么时候处理异常的理解上。在不同的抽象层级上,你要考虑这个异常是不是应该在这个层级上进行处理,还是说应该继续向上抛出,甚至某些情况下还需要包装捕获到的低级异常,再向上抛出。

不同抽象层级上的代码应该只声明抛出同一层级上的异常。

就像处理界面的代码不应该还会捕获处理数据库操作的异常一样。 为了避免这个问题,更高层次的实现需要捕获低层次的异常,包装之后再抛出属于更高层次的异常。这种做法被称作:Exception translation。

try {
    ...
} catch(LowerLevelException e) {
    throw new HigherLevelException(...);
}

当然最完美的情况还是事先完美的层次设计,在调用低层级的方法之前确保它们无论如何都能成功执行,从根本上避免低层抛出异常。实在避免不了,再使用 Exception translation。

在具体处理异常的地方,应当使 try-catch 块尽可能的小,catch 尽可能具体的异常。千万不要捕获 Exception 这么宽泛的异常之后就不管了。

尝试把 try-catch 作为程序流程控制的一部分。比如:

String parm;
try {
    param = jsonObj.getString("parm");
} catch (JSONException e) {
    e.printStackTrace();
    param = "default value";    // 设置一个默认值。
}
// Use param.

这也隐含了一个准则:不要忽略异常。忽略异常最简单的方法就是使用一个空的 catch。即使你确定什么都不需要做,至少也要解释为什么可以什么都不做。
如果你需要自己创建异常,请将对异常的设计放在与程序设计同样的地位。有的开发者可能会用一个大而全的异常类来表示各种不同类型的错误,只通过错误信息来区分不同的错误。这种异常处理方式一方面是不够优雅,另一方面是当你需要进行 Exception translation 时很难对这种大而全的异常进行再包装。

应该仔细设计异常的层次结构,根据不同的情况定义不同的异常类,并在异常类中包含尽量丰富的信息。对于异常提供的信息来说,是程序的内部错误,需要和展示给用户的错误提示区分开来。因此,程序需要保证在和用户交互的层次上,捕获所有抛出的异常,并转换成对应的面向用户的错误提示。

这里只分享了异常处理中的一些原则和思想,如果想了解具体的实践方法可以阅读最后的参考资料。: )

参考资料:

  • Exception handling
  • 深入理解 Java 7:核心技术与最佳实践
  • Effective Java (2nd edition)

欢迎关注知乎专栏「极光日报」,每天为 Makers 导读三篇优质英文文章。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 六种异常处理的陋习 你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握了Java的异常处理机制?在下面这段代...
    Executing阅读 1,374评论 0 6
  • Java异常类型 所有异常类型都是Throwable的子类,Throwable把异常分成两个不同分支的子类Erro...
    予别她阅读 967评论 0 2
  • 初识异常(Exception) 比如我们在取数组里面的某个值得时候,经常会出现定义的取值范围超过了数组的大小,那么...
    iDaniel阅读 1,890评论 1 2
  • 概念介绍 异常是发生在程序执行过程中阻碍程序正常执行的错误事件,当一个程序出现错误时,可能的情况有如下3种: 语法...
    niaoge2016阅读 5,260评论 2 20
  • 这周老师的功课有一个主题是关于这一个。觉察自己想炫耀,希望别人赞美自己的虚荣我执。 其实,我早就看到自己有...
    喜悦能量沙沙阅读 305评论 0 2