Java 异常处理

类的结构如下所示

  • java.lang.Object
    • java.lang.Throwable
      • java.lang.Error
      • java.lang.Exception
        • java.lang.RuntimeException

Throwable类

  • Throwable 类是Java语言中所有错误和异常的超类,只有当一个对象直接或者间接的是此类的实例时,Java才能通过throw语句抛出异常,同样,只有这种类才能被try……catch语句捕获进行处理
  • Throwable类的子类Error是错误,不是程序可以处理的,一般会是内存不足,线程终止,Java虚拟机运行错误等,只能听之任之,JVM通常会kill掉这个进程
  • Throwable类的子类Exception是异常,是程序可以处理的,进一步分为CheckedException 和 UncheckedException
    • CheckedException发生在编译阶段,代码语句必须使用try……catch或者throws,否则无法进行编译,比如StreamTokenizer必须声明抛出异常IOException,除了Runtime Exception类集之外,其他的Exception类集都是CheckeException
    • UncheckedException发生在程序的运行阶段,一般来说具有不确定性,不容易定位和DEBUG

Exception类

  • 该类指出了合理的应用程序想要捕获的异常条件,有两个参数,默认构造可以是两个可选参数,一个是详细信息,一个是异常原因,分别对应下述四个构造方法,分别于super对应
    • public Exception()
    • public Exception(String message)
    • public Exception(String message, Throwable cause)
    • public Exception(Throwable cause)

RuntimeException类

  • RuntimeException是那些在Java 虚拟机正常运行期间抛出的异常的超类,属于uncheckedException,比如说发生数组越界,空指针等逻辑引起的问题
  • 可能在执行方法期间抛出,但是没有被捕获的RuntimeException的任何子类都不用在throws子句中声明
  • 包含四个构造方法
    • RuntimeException()
    • RuntimeException(String message)
    • RuntimeException(String message, Throwable cause)
    • RuntimeException(Throwable cause)

try - catch - finally

  • 在try代码片段中,包含着有可能抛出异常的语句,如果无异常,则直接跳到finally代码块,否则相应的捕获异常,执行catch代码块的内容
  • 无论是否try代码块发生异常,finally都会被执行,可以在这里进行一些接口的close操作等
  • 如果代码中显式的声明了某一个异常类型,则异常处理机制不会显示这个异常是在哪里抛出的,如果是没有声明异常遭遇中断,异常处理会显示出处
  • 每一个catch按照书写的先后依次匹配执行,一旦亦常被某一个catch捕获,则必不会被其他的catch捕获处理
  • 当try代码块或者catch代码块中包括return语句的时候,finally代码块将会在return之前被强制执行,finally不被执行仅仅当下列条件被满足:
    • 代码在finally代码块之前即发生错误
    • 代码在finally代码块之前进行了System.exit()
    • 当前线程由于某种情况丢失
    • 关机,或者各种奇葩的可能条件

throw 和 throws

  • throws 是方法抛出异常的声明,表示一个预动作,说明下方方法可能会抛出异常,throws不做其他处理,仅仅是上交异常到调用,方法中抛出的任何异常都必须有throws声明,除非是将交由运行时系统自动抛出的RuntimeException
  • throw是抛出异常,是一个明确的动作,必须与try……catch或者throws一起使用,抛出的只能是Throwable的类集中的类,如果所有的方法都将异常往上层调用者抛,那么JVM最后的处理就是打印异常消息和堆栈信息

自定义异常类型

一般来说,套路如下:

  1. 定义一个类,继承自Throwable或者某一个子类
  2. 构造方法,或者直接使用super的构造方法
  3. throws声明,在代码块的某处throw该异常类
  4. catch到抛出的异常进行处理

异常链机制

  • 当异常较少的时候,我们可以对每一个异常进行try 和catch, 但是如果出现多个异常,显然通过一个Exception处理所有异常的方式会增加维护代码DEBUG的困难度,所以我们需要将异常信息进行封装,然后捕获我们的异常封装类即可
  • 异常的处理方式有两种,一种是throws抛出异常后交给上级去处理,另一种就是使用try和catch进行具体的修正处理,异常链的处理采用第一种方式,在try ……catch的catch代码块中不做任何处理,唯一的动作就是抛出封装好的异常信息,然后会有throws抛出该异常,递归的每一层都如此控制异常抛出,就形成了一条异常链
  • 如果我们想要在捕获到一个异常后抛出另外一个异常,那么,我们可以调用Throwable类集的getCause()方法,得到类中的cause参数,这个参数保存的就是原始存有的异常信息,也就是说cause是导致抛出该throwable的throwable
  • 保留有异常链的catch代码块中可以使用Throwable的printStackTrace()方法来打印整个异常信息
  • getCause() 返回由一个需要Throwable的构造方法提供的cause,或者是在创建Throwable之后通过initCause()来设定cause,子类不必要重写,也不必重写printStackTrace()
  • printStackTrace()方法会将对象的堆栈跟踪输出到输出流,作为System.err的值

几个建议

  • 尽量在try中不要包含太多的代码,缩小异常范围圈
  • 如果有的接口即使有异常也照样要运行,那么应该使用finally
  • 缩小catch捕获的异常,尽量使catch捕获明确的单个异常
  • 抛出异常的时候,尽量包含易读易懂的描述和名称
  • 不在构造函数中抛出异常,不在finally代码块中处理返回
  • 不要老抛出异常,会降低Java的效率和系统的性能
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值