Java可抛出结构

我们应该知道Java中Throwable是所有异常(Exception)和错误(Error)的超类。首先进入Throwable类看到第一段注释:

The {@code Throwable} class is the superclass of all errors and exceptions in the Java language. Only objects that are instances of this class (or one of its subclasses) are thrown by the Java Virtual Machine or can be thrown by the Java {@code throw} statement. Similarly, only this class or one of its subclasses can be the argument type in a {@code catch} clause.

翻译过来就是:

{@code Throwable}类是Java语言中所有错误和异常的超类。 只有作为此类(或其子类之一)实例的对象才会被Java虚拟机抛出,或者可被Java {@code throw}语句抛出。 类似地,只有这个类或它的一个子类可以是{@code catch}子句中的参数类型。

也就是说Java语言机制中的所有异常处理都应该直接或间接继承自Throwable类,当然也可以直接使用Throwable,但一般不建议这么用。

Java的可抛出结构可以分为受检抛出结构和非受检抛出结构。

javathrow语句(如何分清楚Java的抛出结构)(1)

Java抛出结构

错误(Error)

我们先讲Error。很多人感觉自己在代码中从未使用过Error,这是正确的。因为按照惯例Error往往被JVM保留用于表示资源不足、约束失败或其他无法继续执行的条件。所以开发者在代码中最好不要在实现任何新的Error的子类。那么我们的选择只有一个:你实现的所有非受检的抛出结构都应该是RuntimeException类或者其子类。所以在写代码时就不需要考虑Error的事情了。

受检异常

受检异常通俗来讲就是日常中我们在try...catch...语句中抛出或者捕获的异常。我们最常使用的受检异常是Exception(注意这个)、IOException和SQLException。当然我们也可以自定义很多受检异常。

有些人看到下面运行时异常时会疑惑:运行时异常都继承自RuntimeException类,那是不是受检异常也应该都继承自一个类似CheckedException类?答案是否定的。我们可以进入Throwable源码看一下其注释第二段:

For the purposes of compile-time checking of exceptions, {@code Throwable} and any subclass of {@code Throwable} that is not also a subclass of either {@link RuntimeException} or {@link Error} are regarded as checked exceptions.

翻译过来就是:出于编译时检查异常的目的,{@code Throwable}和{@code Throwable}的任何子类(除了{@link RuntimeException}或{@link Error}类及其子类)都被视为已检查的异常。

也就是说,虽然我们从概念上将受检异常、运行时异常和错误作为并列的三个知识点,但Java语言将除了Error和RuntimeException类及其子类外,其他所有直接或间接继承自Throwable的类都视为受检异常。

很多人习惯直接使用Exception,方便、快捷。但我们为什么有时候要自定义受检异常呢?

Java中一切皆对象,Exception和Error当然也不例外。Exception是对象也就意味这,我们可以在它上面定义任意的方法,实现任意的接口。不过一般我们的目的只是提供分析异常的辅助信息。Exception作为一个基础异常类,提供的信息往往少且抽象。所以我们可以实现自己的受检异常,定制行为和信息。

定制自己的异常非常简单,简单地继承Throwable类或者Exception类,然后在构造方法中调用父类构造方法即可。但这样没有定制功能的自定义受检异常没有任何意义。可以为自定义异常类添加信息处理方法等使其变得有意义。

运行时异常

运行时异常不需要也不应该被我们捕获。常见的运行时异常一般有:参数非法(IllegalArgumentException)、空指针异常(NullPointerException)、下标越界(IndexOutBoundsException)等,它们都继承自RuntimeException类。

这些异常都不陌生,在调试项目的时候遇到问题Terminal经常会报一大堆红:xxxx NullPointerException at:org.xxx.xxx 巴拉巴拉一大堆,这些就是运行时异常。

要注意,运行时异常不应该被捕获,但并不意味着不能被捕获,在代码中把它放在catch后面或者用throw语句抛出,语法允许,不会报错。既然Throwable类且其子类都能被捕获和抛出,RuntimeException当然不例外。不过虽然代码语法不错,但从逻辑上讲,系统发生运行时异常往往不可恢复,继续执行有害无益应该终止,所以不应该捕获。

Java泛型和通配符类型你真的能搞清楚吗

其实Java枚举类和普通类没什么区别

Java字符串:StringBuilder 和 StringBuffer

,