在Java中,当你需要统一处理异常的时候,你是会选择catch (Exception),还是直接catch (Throwable)?

Java的异常体系

  • Throwable: Java中所有异常和错误类的父类。只有这个类的实例(或者子类的实例)可以被虚拟机抛出或者被java的throw关键字抛出。同样,只有其或其子类可以出现在catch子句里面。
  • Error: Throwable的子类,表示严重的问题发生了,而且这种错误是不可恢复的。
  • Exception: Throwable的子类,应用程序应该要捕获其或其子类(RuntimeException例外),称为checked exception。比如:IOException, NoSuchMethodException...
  • RuntimeException: Exception的子类,运行时异常,程序可以不捕获,称为unchecked exception。比如:NullPointException.

应该catch什么

其实只要是Throwable和其子类都是可以throw和catch的,那么如果在需要统一处理异常的地方,我们应该catch (Throwable th) 还是 catch (Exception)呢?

这两种处理的区别在于,catch throwable会把Error和其他继承Throwable的类捕捉到。而catch Exception只会捕捉Exception极其子类,捕捉的范围更小。先不考虑有其他的类继承了Throwable的情况下(附录A),第一种catch相当于比第二种catch多捕捉了把Error和其子类。

那么究竟Error是否需要捕捉呢?JDK中Error类的的注释(如下)里提到过,Error是一种严重的问题,应用程序不应该捕捉它。

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.

A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.

Java Lanuage Spec 7 中也提到:Error继承自Throwable而不是继承自Exception,是为了方便程序可以使用 "catch (Exception)"来捕捉异常而不会把Error也捕捉在内,因为Exception发生后可以进行一些恢复工作的,但是Error发生后一般是不可恢复的。

The class Error is a separate subclass ofThrowable, distinct from Exception in the class hierarchy, to allow programs to use the idiom "} catch (Exception e) { " (§11.2.3) to catch all exceptions from which recovery may be possible without catching errors from which recovery is typically not possible.

已经不难看出,Java本身设计思路就是希望大家catch Exception就足够了,如果有Error发生,catch了也不会有什么作用(附录B)。


引申,如何设计异常体系?

如何设计异常体系要根据你的项目的情况,类库框架,应用程序的异常设计方式都会有一些区别。下面简单谈谈个人对异常设计的一些看法

类库/框架

  • 继承RuntimeException扩展一个新的异常作为整个类库的异常基类。这个异常应该可以满足大部分类库对异常的要求。
  • 在实现中,在任何需要捕捉checked exception的地方都会把异常统一转化成这个新的异常。
  • 对于有特殊需求,需要自定义异常的,就通过继承这个基类来实现自定义异常。
  • 不对异常记录log(交给上层来处理)
  • 案例
    • fastjson 
    • spring 自定义异常比较多,不过都是继承自org.springframework.core.NestedRuntimeException,而这个异常也是继承自RuntimeException。

应用程序

  • 设计上和框架异常类似,只是在捕捉checked exception的时候需要log
  • 如果需要根据异常进行不同的处理,建议给自定义异常增加一个ERROR_CODE字段,这样无论在服务器还是客户端都可以根据不同的ERROR_CODE进行对应的处理。但是出现这种情况的时候,应该需要考虑一下设计思路了,一般来讲根据异常来决定业务流程不是一个好的设计方案。

附录A:是否应该直接继承Throwable来扩展新的异常?

个人认为异常都应该继承自Exception或者RuntimeException,而且Java本身对Exception和Error的规划就很清晰了,Java自己类库中没有异常是直接继承自Throwable的。

附录B:Error可以catch吗? 可以catch了后做些其他处理吗?

Error是可以catch的,而且也可以向常规Exception一样被处理,而且就算不捕捉的话也只是导致当前线程挂掉,其他线程还是可以正常运行,如果有需要的话捕捉Error之后也可以做些其他处理。但是Error是一种系统内部的错误,这种错误不像Exception一样是可能是程序和业务上的错误是可以恢复的。

假设进行网络连接操作的时候,IOException 发生了,可能是网络中断,我可以再尝试几次。

假设OutOfMemoryError发生了,就算被捕捉了,可以有什么手段让程序正常运行下去吗? 假设ExceptionInInitializerError发生了,类无法被正常初始化,这个是可以通过捕捉来恢复的吗?

如何处理异常? catch Exception OR catch Throwable的更多相关文章

  1. 异常类Exception(String message, Throwable cause)中的cause理解

    这个在构造函数里面竟然有一个Throwable,感觉有些奇怪. 1. Throwable cause 这里cause要传一个Throwable的子类异常进去么? 是引起这个异常的异常,如果这个值是空值 ...

  2. Java中有多个异常, 如何确定捕获顺序(多个catch),先从上到下执行,判断异常的大小,如果包含捕到异常,就进入这个catch,后面的就不再执行

    Java中异常的捕获顺序(多个catch)( Java代码 import java.io.IOException; public class ExceptionTryCatchTest { publi ...

  3. JAVA不经过Catch(Exception e)直接到finally或者退出原因

    今天遇到一个很奇葩的问题!在写Hadoop程序的时候!new一个对象!程序直接跑到finally代码块里面去了!Catch里面的Exception也没有执行. Configuration config ...

  4. 前端魔法堂——异常不仅仅是try/catch

    前言  编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外.对于业务用例的例外我们别无它法,必须要求实施人员与 ...

  5. (后端)异常不仅仅是try/catch

    前言  编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外.对于业务用例的例外我们别无它法,必须要求实施人员与 ...

  6. 处理异常的 try,catch

    try catch finally 1.将预见可能引发异常的代码包含在try语句块中. 2.如果发生了异常,则转入catch的执行.catch有几种写法: catch 这将捕获任何发生的异常. cat ...

  7. Java异常之try,catch,finally,throw,throws

    Java异常之try,catch,finally,throw,throws 你能区分异常和错误吗? 我们每天上班,正常情况下可能30分钟就能到达.但是由于车多,人多,道路拥挤,致使我们要花费更多地时间 ...

  8. Java解决异常之try、catch、finally、throw、throws&log4j记录日志步骤

    知识点一.多重catch引发多种类型的异常排列catch 语句的顺序:先子类后父类 发生异常时按顺序逐个匹配只执行第一个与异常类型匹配的catch语句二.异常分类异常分为运行时异常和检测异常运行时异常 ...

  9. 【Java】异常 —— throw, throws, try catch 相关内容

    嗯……面试考到了这个,又是一个如无意外 那么接下来就总结吧 一.什么是异常 程序运行过程中发生的异常事件. RuntimeException通常是因为编程员因为疏忽没有检查而引起的错误. 二.Exce ...

随机推荐

  1. fastjson List<> 转Json , Json 转List<>

    SerializeWriter:相当于StringBuffer JSONArray:相当于List<Object> JSONObject:相当于Map<String, Object& ...

  2. lua学习笔记(十二)

    弱引用table     lua使用自动内存管理机制,通过垃圾回收器来回收内存     垃圾回收器只能回收它认为是垃圾的内容,而不能回收用户认为是垃圾的内容     典型的例子栈,栈一般用一个数组和一 ...

  3. lua学习笔记(二)

    开始   程序块chunk     交互模式里输入的一行代     一个文件里的代码     也就是一连串的语句或命令     连续的lua语句之间不需要分隔符,但也可以使用分号,如果你愿意的话   ...

  4. websocket通讯协议(10版本)简介

    前言: 工作中用到了websocket 协议10版本的,英文的协议请看这里: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotoc ...

  5. Spring Boot - 配置信息后处理

    最近在做项目的过程中,PSS提出配置文件中类似数据库连接需要的用户名.密码等敏感信息需要加密处理(之前一直是明文的). 为了快速完成任务,网上搜刮到jasypt包,也有相应的starter,使用方法可 ...

  6. eclipse maven 依赖jar下载失败解决办法

    针对PC与Maven私服之间网络传输问题 打开.m2本地仓库所在目录, 通过win文件夹的搜索功能,查找 *.lastUpdated ,然后将找到的文件全部删除 重新 Maven Update Pro ...

  7. UIview层次管理

    将一个UIView显示在最前面只需要调用其父视图的 bringSubviewToFront()方法. 将一个UIView层推送到背后只需要调用其父视图的 sendSubviewToBack()方法.

  8. 腾讯课堂十大Excel函数

    十大函数:if,sumifs,countifs,vlookup,match,index,indirect,subtotal,left(mid,right),offset substotal:用于灵活计 ...

  9. erlang的md5加密

    二话不说,直接上代码 -module(md5). -compile(export_all). md5(S) -> Md5_bin = erlang:md5(S), Md5_list = bina ...

  10. 计算CPU利用率

    一般来说对于需要大量cpu计算的进程,当前端压力越大时,CPU利用率越高.但对于I/O网络密集型的进程,即使请求很多,服务器的CPU也不一定很到,这时的服务瓶颈一般是在磁盘的I/O上.比较常见的就是, ...