什么是异常
正如文档开头所说,世界上并没有完美的程序,程序在运行中可能会存在着异常状态
,这种异常状态,可能是异常(Exception),也可能是错误(Error),一个健壮性的程序就要考虑程序可能存在的异常状态
,并对其进行处理。Throwable
类是Java中所有错误和异常的超类,位于java.lang
包,从JDK1.0开始引入。Throwable有两个子类Exception(Java中所有异常类的父类)和Error(Java中所有错误类的父类)。
![](https://i-blog.csdnimg.cn/blog_migrate/91a68e172ccb9af2bcadc8dd0b87fee8.png)
错误往往是程序运行时发生,程序员不可控制,对程序造成不可逆转的影响,比如Java中OutOfMemoryError,内存溢出,导致程序宕机,错误在代码中通常被忽略,它们在编译也检查不到的,当然好的编程习惯合理运用各种数据结构,提升代码质量等等会减少OOM的发生率。
异常会在编译或者运行时被发现,需要程序员去处理一部分异常,捕获异常,并合理的处理能保证程序的健壮性,让程序继续往下执行,不至于某个部分异常影响到整个应用,因此Java中异常类(Exception)是需要重点去学习关注的,下面所说的异常也都指Exception及其子类出现的异常
- 受检异常(CheckedException)
- 一般由外部错误引起,发生在编译阶段,Java编译器会强制捕获这类异常,要求使用try catch捕获。
- 如果期望调用者能够适当的恢复,应该使用受检异常。
- 运行时异常(RuntimeException)
- 在Java虚拟机运行期间抛出的异常,出现运行时异常,通常都是程序员的错误导致的。
- 使用运行时异常表示编程错误,不应该也不需要捕获运行时异常。
常见异常
Java中内置了一些异常类来描述程序可能出现的受检异常和运行时异常。
- 运行时异常
异常 | 描述 |
---|---|
ArithmeticException | 算术异常,运算条件错误时抛出,比如 int i = 1 / 0 |
ArrayIndexOutOfBoundsException | 数组越界异常,用非法索引(索引大于小于数组边界)访问数组边界时抛出的异常。 |
ClassCastException | 类型转换异常,将对象强制转换为不是实例的子类时,抛出该异常,如多态。 |
IllegalArgumentException | 非法参数异常,当传入参数不符合规范时出现,如前台表单传送至后台 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
- 受检异常
异常 | 描述 |
---|---|
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常,如加载JDBC 驱动时。 |
CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出该异常,如调用线程的wait ,sleep 等方法时。 |
NoSuchFieldException | 请求的变量不存在时抛出 |
NoSuchMethodException | 请求的方法不存在时抛出,如前台js请求struts方法配置错误时。 |
异常处理
程序产生的运行时异常往往是程序员的错误导致的,不应该去捕获运行时异常,受检异常需要我们去处理,保证程序的健壮性。Effecive Java中对于异常的处理通常有下面几种原则:
- 异常应该只用于异常情况下,不应该用作流程控制
- 对可恢复的情况使用受检异常,对编程错误使用运行时异常
- 避免不必要的使用受检异常
- 优先使用标准异常
- 努力使失败保持原子性,失败的方法调用应该保持对象在调用之前的状态
- 不要忽略异常
参考资料
Effective Java第三版