第七章--第二节:错误和异常的处理

第七章:软件构造的健壮性

第二章:错误和异常的处理

问题一:Java中的错误和异常

java.lang.Throwable 包含:java.lang.Exception、java.lang.Error。

第七章--第二节:错误和异常的处理

内部错误(Error):程序员通常无能为力,一旦发生,想办法让程序优雅的结束

异常(Exception):你自己程序导致的问题,可以捕获、可以处理

问题二:错误(Error)

    分类:

  • User input errors 用户输入错误
  • Device errors 设备错误
  • Physical limitations 物理限制

    典型的错误:

第七章--第二节:错误和异常的处理

问题三:异常的处理(既然Error我们无能为力,那就转向关注我们能处理的Exception)

    1.异常:程序执行中的非正常事件,程序无法再按预想的流程执行。

    2.异常处理

  • 将错误信息传递给上层调用者,并报告“案发现场”的信息。
  • return之外的第二种退出途径
  • 若找不到异常处理程序,整个系统完全退出

*:对比使用异常处理和不使用异常处理

    ①不使用异常处理

第七章--第二节:错误和异常的处理

    ②使用异常处理

第七章--第二节:错误和异常的处理

    3.异常的分类

  • 运行时异常(Exceptions that derive from RuntimeException):由程序员处理不当造成
  • 其他异常:由外部原因造成(是程序员无法完全控制的外在问题导致的)

问题四:Checked and unchecked exceptions(异常被谁check?——编译器、程序员)

    1.Checked exception:编译器可帮助检查你的程序是否已抛出或处理了可能的异常

第七章--第二节:错误和异常的处理

    **:

checked exception:

第七章--第二节:错误和异常的处理

第七章--第二节:错误和异常的处理

    对Checked Exception的处理操作:

  • throws:声明“可能会发生异常”
  • throw:抛出异常
  • try,catch,finally:捕获并处理异常

    2.Unchecked exception(Error + RuntimeException):程序员对此不能做任何是事情,不得不重写你的代码。(不需要在编译的时候用try…catch等机制处理)

第七章--第二节:错误和异常的处理

    常见的Unchecked exception:

  • ArrayIndexOutOfBoundsException: thrown by JVM when yourcode uses an array index, which is outside the array's bounds.
  • NullPointerException: thrown by the JVM when your codeattempts to use a null reference where an object reference isrequired.
  • NumberFormatException: Thrown programmatically (e.g., byInteger.parseInt()) when an attempt is made to convert a stringto a numeric type, but the string does not have the appropriateformat.
  • ClassCastException: thrown by JVMwhen an attempt is made to cast an object reference fails.
  • IllegalArgumentException: thrown programmatically to indicatethat a method has been passed an illegal or inappropriate argument.You could re-use this exception for your own methods.
  • IllegalStateException: thrown programmatically when a methodis invoked and the program is not in an appropriate state for thatmethod to perform its task. This typically happens when a method isinvoked out of sequence, or perhaps a method is only allowed to beinvoked once and an attempt is made to invoke it again.
  • NoClassDefFoundError: thrown by the JVM or class loader whenthe definition of a class cannot be found.

    **

    unchecked exception:

第七章--第二节:错误和异常的处理

    第七章--第二节:错误和异常的处理

    3.如何决定使用哪种异常处理?

    当要决定是采用checked exception还是Uncheckedexception的时候,问一个问题:“如果这种异常一旦抛出,client会做怎样的补救?”

选用Unchecked exception:客户端代码不能做任何事情

选用Checked exception:客户端代码将基于异常的信息采取一些有用的恢复措施。

  • 如果客户端可以通过其他的方法恢复异常,那么采用checked exception;
  • 如果客户端对出现的这种异常无能为力,那么采用unchecked exception;
  • (异常出现的时候,要做一些试图恢复它的动作而不要仅仅的打印它的信息。)
  • 尽量使用unchecked exception来处理编程错误:因为uncheckedexception不用使客户端代码显式的处理它们,它们自己会在出现的地方挂起程序并打印出异常信息。
  • 如果client端对某种异常无能为力,可以把它转变为一个unchecked exception,程序被挂起并返回客户端异常信息
  • 不要创建没有意义的异常,client应该从checked exception中获取更有价值的信息(案发现场具体是什么样子),利用异常返回的信息来明确操作失败的原因。– 如果client仅仅想看到异常信息,可以简单抛出一个unchecked exception:throw new RuntimeException("Username already taken");
  • 错误可预料,但无法预防,但可以有手段从中恢复,此时使用checkedexception;如果做不到这一点,则使用unchecked exception
    第七章--第二节:错误和异常的处理

总结:– Checked exception应该让客户端从中得到丰富的信息。

          – 要想让代码更加易读,倾向于用unchecked exception来处理程序中的错误。

问题五:通过throws声明Checked Exceptions

  •     使用throws声明异常:此时需要告知你的client需要处理这些异常,如果client没有handler来处理被抛出的checked exception,程序就终止执行。
  • 程序员必须在方法的spec中明确写清本方法会抛出的所有checked exception,以便于调用该方法的client加以处理
  • 在使用throws时,方法要在定义和spec中明确声明所抛出的全部checked exception,没有抛出checked异常,编译出错,Unchecked异常和Error可以不用处理。

异常中的LSP原则:

  • 如果子类型中override了父类型中的函数,那么子类型中方法抛出的异常不能比父类型抛出的异常类型更广泛
  • 子类型方法可以抛出更具体的异常,也可以不抛出任何异常
  • 如果父类型的方法未抛出异常,那么子类型的方法也不能抛出异常。
  • 其他的参考第五章第二节的LSP

问题六:用throw抛出一个异常

:你要抛出一个EOFException,你可以:

    第七章--第二节:错误和异常的处理

  •     利用Exception的构造函数,将发生错误的现场信息充分的传递给client。

第七章--第二节:错误和异常的处理

    步骤:

  1. 找到一个能表达错误的Exception类/或者构造一个新的Exception类
  2. 构造Exception类的实例,将错误信息写入
  3. 抛出它

(一旦抛出异常,方法不会再将控制权返回给调用它的client,因此也无需考虑返回错误代码)

问题七:创建异常类(自定义异常)

    如果JDK提供的exception类无法充分描述你的程序发生的错误,可以创建自己的异常类。

    *:自定义checked异常

第七章--第二节:错误和异常的处理

第七章--第二节:错误和异常的处理

*:自定义Unchecked异常

第七章--第二节:错误和异常的处理

第七章--第二节:错误和异常的处理

*:自定义异常可以包含更多的信息

第七章--第二节:错误和异常的处理

问题八:捕获异常

    模式:

    第七章--第二节:错误和异常的处理

一般的原则:

  • 尽量在自己这里处理,实在不行就往上传——要承担责任!;但有些时候自己不知道如何处理,那么提醒上家,由client自己处理(使用throws关键字)
  • 如果父类型中的方法没有抛出异常,那么子类型中的方法必须捕获所有的checked exception
  • 子类型方法中不能抛出比父类型方法更多的异常!

获取异常的细节:

    e.getMessage():to get thedetailed error message (if there is one)

    e.getClass().getName():to get the actual type of theexception object.

问题九:Rethrowing and ChainingExceptions

    含义:本来catch语句下面是用来做exception handling的,但也可以在catch里抛出异常

    目的:更改exception的类型,更方便client端获取错误信息并处理

    *:

第七章--第二节:错误和异常的处理

(但这么做最好也要保留跟原因):

第七章--第二节:错误和异常的处理

问题十:Finally语句

    场景:当异常抛出时,方法中正常执行的代码被终止;但如果异常发生前曾申请过某些资源,那么异常发生后这些资源要被恰当的清理,所以需要用finally语句。

    ***

    ①:

第七章--第二节:错误和异常的处理

    ②:

    第七章--第二节:错误和异常的处理

    ③:

    第七章--第二节:错误和异常的处理


也可以没有catch,直接用finally

第七章--第二节:错误和异常的处理