如何处理异常? catch Exception OR catch Throwable

在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发生了,类无法被正常初始化,这个是可以通过捕捉来恢复的吗?

时间: 2024-10-13 11:20:20

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

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

今天遇到一个很奇葩的问题!在写Hadoop程序的时候!new一个对象!程序直接跑到finally代码块里面去了!Catch里面的Exception也没有执行. Configuration configuration = new Configuration(); 害我纳闷了好久!就去看了Hadoop的源码!new这个对象的时候也没执行哪些操作,只是一些正常的赋值而已!后来网上找了很久才发现,原来是被变成Throwable抛出来了!而Exception是Throwable的子类,所以无法捕捉到,只有

异常和try、catch、finally的简记

一.异常的简记 1)Java异常和错误的基类是Throwable(java.lang.Throwable),包括Exception(异常)和Error(错误). 2)try和catch不一定需要共存,try是尝试对其中代码捕获异常,catch是捕获异常并且可以处理异常.假如try中有异常抛出,则会去执行catch块,再去执行finally块:假如没有catch块,可以直接执行finally块,方法就以抛出异常的方式结束,而finally 后的内容也不会被执行,所以catch 和 finally

处理异常的 try,catch

try catch finally 1.将预见可能引发异常的代码包含在try语句块中. 2.如果发生了异常,则转入catch的执行.catch有几种写法: catch 这将捕获任何发生的异常. catch(Exception e) 这将捕获任何发生的异常.另外,还提供e参数,你可以在处理异常时使用e参数来获得有关异常的信息. catch(Exception的派生类 e) 这将捕获派生类定义的异常,例如,我想捕获一个无效操作的异常,可以如下写: catch(InvalidOperationExce

c# - catch(Exception ex) 会丢掉StackTrace 是怎么回事?

原本这篇文章就想写写StackTrace怎么会丢的问题, 但现在的内容变成了讨论怎么处理Exception的问题. 该不该用try catch, 什么时候用?也困扰了我很久, 好像随便写写就可以, 但是事实上还是有Best Practise, 以下内容请您参考,欢迎指正! StackTrace: 保存方法的栈调用信息. 什么意思呢?A方法里调用了B方法,B方法里调用了C方法,你调用A方法的时候StackTrace里就大概是这样: at Project.Class.C in c:\aaa\Proj

在zend framework框架中try{}catch(Exception e){}的跳转问题

请勿盗版,转载请加上出处http://blog.csdn.net/yanlintao1 首先我先说明我遇到的问题 try{ //导入学生信息 $ModelStudent->insert($data2); } catch (Exception $e) { unlink(DOCS_PATH.'/student.xls'); $this->view->str = '导入失败,请检查数据格是否正确!'; $this->_forward("error","glo

Java 异常基础 Exception

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 1. 引子 try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解.不过,我亲自体验的“教训”告诉我,这个东西可不是想象中的那么简单.听话.不信?那你看看下面的代码,“猜猜”它执行后的结果会是什么?不要往后看答案.也不许执行代码看真正答案哦.如果你的答案是正确,那么这篇文章你就不用浪费时间看啦. [java] view plaincopyprint? <span s

异常:exception和error的区别

Throwable 是所有 Java 程序中错误处理的父类 ,有两种子类: Error 和 Exception . Error :表示由 JVM 所侦测到的无法预期的错误,由于这是属于 JVM 层次的严重错误 ,导致 JVM 无法继续执行,因此,这是不可捕捉到的,无法采取任何恢复的操作,顶多只能显示错误信息. Exception :表示可恢复的例外,这是可捕捉到的. Java 提供了两类主要的异常 :runtime exception 和 checked exception . checked

C# 知识回顾 - 你真的懂异常(Exception)吗?

你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally 等,用来处理失败的情况. CLR..NET 自身的类库.其它第三方库或者你写的程序代码都有可能会出现异常

java的异常(Exception)信息的详细记录

java的异常(Exception)信息的详细记录获取Exception的详细信息下面的三个方法都是获取异常的详细信息,或许的异常详细信息以字符串的形式返回,保持栈堆的风格 方法一: public static String getExceptionAllinformation(Exception ex){         String sOut = "";         StackTraceElement[] trace = ex.getStackTrace();