Java Exception

异常处理

安全检查及错误处理

编程中的对于带参方法进行方法传参时,必须对所传参数进行安全检查,不能假定使用者一定会传入正确的值。但如果检查到传入参数不合法时,由方法去终止程序的运行显然是一个问题。不应该让方法来终止程序——应该由方法的调用者来决定是否终止程序。

当进行安全检查时,若传入参数不合法,而如上述由方法去终止程序又显然是不合理的,此时就可以由方法去抛出一个异常,(throw)

当异常被抛出时,正常的执行流程就会被中断,而异常则会被从方法处转移到其调用者处,由调用者决定如何处理异常

进行异常处理的好处

  • 它能够使方法抛出一个异常,并由调用者决定如何处理该异常
  • 异常处理的根本优势就是将检查错误(由被调用者处)从处理错误(由调用者方法完成)中分离出来

异常的体系结构

Throwable 
    |-- Error 
         |-- OutOfMemoryError 内存溢出 
         |-- VirtualMatchineError 虚拟机崩溃
         |-- ... 
    |-- Exception 
         |-- ClassNotFoundException 试图使用一个不存在的类 
         |-- IOExceprtion IO异常 
         |-- RuntionException 运行时异常 
               |-- NotNullPointException 空指针异常 
               |-- IndexOutOfBoundsExcepton 数组下标越界 
               |-- ArithmeticException 一个整数除以0 
               |-- IllegalArgumentException 传入方法参数不合法 
         |-- ...

Throwable类是所有异常类的根类,所有异常类都直接或间接的继承自Throwable类。

异常的分类

异常可以分为三种类型:系统错误(Error)、编译时异常(Exception)、运行时异常(RuntimeException)

系统错误(Error)

该异常是由java虚拟机抛出的,描述了系统内部错误,很少发生,发生时除了终止程序,什么都做不了

OutOfMemoryError : 内存溢出
VirtualMatchineError 虚拟机崩溃
...

编译时异常(Exception)

该异常描述了程序或外部环境所引起的错误,这些错误可以被捕获和处理.

在IDE中进行编码时,如果出现编译异常,那么IDE会出现错误提示。

ClassNotFountException
IOException
...

运行时异常(RuntimeException)

描述了程序设计的错误,运行时异常通常是由java虚拟机抛出的。

在IDE中进行编码时,若出现运行时异常IDE不会有任何提示,因为运行时异常通常表现为程序的逻辑错误。

编译器不要求对抛出的运行时异常进行处理,也就是说既不捕获也不声明抛出

ArithmeticException  一个整数除以0 
NullPointException 
IndexOutOfBoundsException 
IllegalArgumentException  传递给方法的参数不合法,或者不合适
...

注意

免检异常(Unchecked Exception):

Error、RuntimeException以及它们的子类都称之为免检异常(Unchecked Exception):通常反映了程序设计上不可恢复的逻辑错误,不要求在方法中显示声明Error和RuntionException

必检异常(Checked Exception):

所有的其他异常都称为必检异常(Checked Exception):意思是说编译器会强制要求程序员检查并通过try-catch处理或者在方法头声明(throws) 每个方法都必须声明它可能抛出的必检异常

异常的三种处理方式

异常处理的三种操作:声明一个异常(throws)、抛出一个异常(throw)、捕获一个异常(try-catch-finally)

声明一个异常(throws)

对于方法抛出的异常,可以采用在当前方法头中声明一个异常的方式进行处理

public void test(...) throws Exception {
    ...
}

注意:在继承过程中,如果父类定义的方法有抛出异常,
那么子类在继承父类方法时,可以不抛出异常,
或者抛出和父类相同或者更小的异常

抛出一个异常(throw)

在编码时,对将可能发生的错误可以采用抛出异常的方法进行处理,以便当异常发生时方法的调用者进行处理,其格式如下:

throw new Exception(...);
自定义异常

当系统类库中提供的异常类不能满足需要时,我们需要自定义异常类

自定义异常需要继承自系统的编译时异常或者运行时异常,若要输出相应 的异常信息,可以自定义构造器方法并调用super()

在IDE中编码时,可以通过IDE自动编写并重载构造器

捕获一个异常 (try-cathc-finally)

处理异常的代码称为异常处理器,可以从当前方法开始,
沿着方法调用链, 按照异常的反向传播方向找到该处理器

一个通用的父类可以派生出各种子类。如果一个catch块可以捕获一个父类异常,
那么它就能够捕获 那个父类的所有子类的异常对象,因此在catch块中异常被指定的顺序时非常重要的,如果父类的catch块出现在子类的catch块之前 就会发生编译错误

在JDK7 后对于使用同样的处理代码处理多个异常的情况,可以使用新的多捕获
特征 (multi-catch feature) 简化异常的代码编写。语法是:

catch (Exception1 | Exception2 | Exception3 | ... e) { ... }

注意:该语法下,catch中的Exception之间不能存在继承关系

try/catch/finally的使用
  • try: 在try代码块中编写可能会发生异常的代码
  • catch: 在catch代码块中捕获try可能会发生的异常以及在该异常发生后需要进行的处理操作
  • finally: 有些特定的代码无论异常是否发生都需要执行,finally用于执行这一类代码,以避免当程序发生时异常进行跳转时,这一部分代码无法执行的情况。如释放一些资源等
  • try不能单独使用,必须和catch或者finally结合才能使用,也就是说catch和finally都不是必须的,但至少出现一个

注意:finally块中一般不谢return,try-catch中一旦执行return,那么做两件事:1. 将返回值存入JVM缓冲区中 2. 如果有finally, 则现将finally执行完,然后结束方法,返回缓冲区中的值

捕获异常的注意点:
  1. 如果可能捕获的异常之间存在继承关系,那么子类应该写在前边
  2. catch()中可以捕获多个异常, 但多个异常之间不能有继承关系
    try{}catch(异常名1 | 异常名2 e){}
  3. try/catch/finally结构中try不能单独存在。可以分别符catch或finally结合,或者三者都存在

你可能感兴趣的:(java学习笔记)