Java异常分类、声明、创建、捕获、技巧

Java异常分类、使用、自定义

概念

​ 如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。

分类

Throwable是 Java语言中所有错误或异常的超类。下一层分为Error和Exception。
Java异常分类、声明、创建、捕获、技巧_第1张图片

Error类是指Java运行时系统的内部错误和资源耗尽错误。应用程序不应抛出该类对象。如果出现了这样的错误,除了告知用户,剩下的就是尽力使程序安全地终止。

Exception类有两个分支,一个分支派生于RuntimeException,另一个分支包含其他异常。由于程序错误导致的异常属于RuntimeException;而程序本身没有问题,但由于像I/O错误这类问题导致的异常属于其他异常。如果出现RuntimeException异常,就一定是程序员的错误。

Java语言规范将派生于Error类或RuntimeException类的所有异常称为非受查异常,所有其他的异常称为受查异常。编译器将核查是否为所有的受查异常提供了异常处理器。

声明受查异常

​ 一个方法必须声明所有可能抛出的受查异常, 而非受查异常要么不可控制( Error),要么就应该避免发生( RuntimeException )。如果方法没有声明所有可能发生的受查异常, 编译器就会发出一个错误消息。

​ 如果在子类中覆盖了超类的一个方法, 子类方法中声明的受查异常不能比超类方法中声明的异常更通用(也就是说, 子类方法中可以抛出更特定的异常, 或者根本不抛出任何异常)。特别需要说明的是, 如果超类方法没有抛出任何受查异常, 子类也不能抛出任何受查异常。

throw和throws的区别

位置不同:throws用在函数上,后面跟的是异常类,可以跟多个;而throw用在函数内,后面跟的是异常对象。

功能不同:

​ throws用来声明异常,让调用者只知道该功能可能出现的问题,可以给出预先的处理方式;throw抛出具体的问题对象,执行到throw,功能就已经结束了,跳转到调用者,并将具体的问题对象抛给调用者。也就是说throw语句独立存在时,下面不要定义其他语句,因为执行不到。

​ throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。

​ 两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。

创建异常类

​ 定义一个派生于Exception的类, 或者派生于Exception子类的类。习惯上, 定义的类应该包含两个构造器, 一个是默认的构造器;另一个是带有详细描述信息的构造器(超类Throwable的toString方法将会打印出这些详细信息, 这在调试中非常有用)。

捕获异常

​ 通常,应该捕获那些知道如何处理的异常,而将那些不知道怎样处理的异常继续进行传递。同时,这个规则也有例外:如果编写一个覆盖超类的方法,而这个方法又没有抛出异常, 那么这个方法就必须捕获方法代码中出现的每一个受查异常。不允许在子类的throws说明符中出现超过超类方法所列出的异常类范围。

​ 异常堆栈路径无论如何都会记住它的真正起点,无论自己被重复“throw”了好几次。若想安装新的堆栈跟踪信息,可调用fillInStackTrace(),它会返回一个特殊的异常对象。这个异常的创建过程如下:将当前堆栈的信息填充到原来的异常对象里。

​ Throwable在任何异常规范中都不是必需的。永远不必关心如何清除前一个异常,或者与之有关的其他任何异常。它们都属于用new创建的、以内存堆为基础的对象,所以垃圾收集器会自动将其清除。

​ 同一个catch子句中可以捕获多个异常类型。同时异常变量隐含为final 变量,不能在子句体中为异常赋不同的值,并且只有当捕获的异常类型彼此之间不存在子类关系时才需要这个特性。

异常机制的技巧

  • 异常处理不能代替简单的测试

  • 不要过分地细化异常

  • 利用异常层次结构

  • 不要压制异常

  • 在检测错误时,“ 苛刻” 要比放任更好

  • 不要过分地细化异常

  • 利用异常层次结构

  • 不要压制异常

  • 在检测错误时,“ 苛刻” 要比放任更好

  • 不要羞于传递异常

你可能感兴趣的:(java)