目录
异常是程序中的一些错误,但并不是所有的错误都是异常。
一、异常
(一)异常的相关概念
异常,指程序在运行过程中,出现的非正常的情况,最终会导致java虚拟机(jvm)的非正常停止。
异常处理的必要性,减少用户的损失,同时减少给用户带来的不必要的麻烦,也可以利用异常处理给与用户一些提示。
异常机制,指当程序出现错误后,程序如何处理。
程序错误:
- 编译错误——程序没有遵循语法规则,编译程序能够自己发现并提示我们错误的原因和位置;
- 运行时错误——程序在执行时,运行环境发现了不能执行的操作;
- 逻辑错误——程序没有按照预期的逻辑顺序执行。
(二)异常产生的原因
Java中异常的产生,主要有以下三种原因:
- Java内部错误发生异常,Java虚拟机产生的异常;
- 编写程序代码的错误,例如,空指针异常、数组越界等异常;
- 通过throw语句手动生成的异常。
(三)异常的分类
异常有的是因为用户的错误引起,有的是程序错误引起,还有其他的是因为物理错误引起。
常见的三种类型的异常:
- 检查性异常——用户错误或问题引起的异常,例如,打开一个不存在文件。此类异常程序猿无法预见;
- 运行时异常——此类异常程序猿是可以避免的异常;
- 错误——错误不是异常,是脱离程序猿控制的问题。错误在代码中通常被忽略,例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
二、Exception
所有的异常类是从java.lang.Exception类继承的子类,而Exception类和Error是Throwable类的子类。
(一)检查性异常
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出异常。 |
CloneNotSupportedexception | 当调用Object类中的clone方法克隆对象,但该对象的类无法实现Cloneable接口时,抛出异常。 |
IllegalAccessException | 拒绝访问一个类时,抛出异常。 |
InstantiationException | 当试图使用Class类中的newInstance方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出异常。 |
NoSuchFieldException | 请求的变量不存在。 |
NoSuchMethodException | 请求的方法不存在。 |
(二)非检查性异常
ArithmeticException | 当出现异常的运算条件时,抛出异常。例如,11/0 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时,抛出异常。若索引小于0或大于array.length,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时,抛出异常。 |
ClassCastException | 试图将对象强制转换为不是实例的子类时,抛出异常。 |
IllegalArgumentException | 向方法传递了一个不合法或不正确的参数,抛出异常。 |
IllegalMonitorStateException | 某一线程已经试图等待对象的监视器,或试图通知其他正在等待对象的监视器而本身没有指定监视器的线程,抛出异常。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。即Java环境或Java应用程序没有处于请求操作所要求的的适当状态。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态,抛出异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
(三) 异常方法
public String getMessage() | 返回关于发生的异常的详细信息。 |
public Throwable getCause() | 返回一个Throwable对象代表的异常原因。 |
public String toString() | 返回此Throwable的简短描述。 |
public void printStackTrace() | 将此 Throwable 及其回溯打印到标准错误流。 |
public StackTraceElement [] getStackTrace() | 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 |
public Throwable fillInStackTrace() | 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。 |
三、Java处理异常的关键字
Java异常处理的关键字:try,catch,finally,throw,throws
(一)捕获异常
try/catch 捕获异常
try/catch 语法
// 捕获异常
try{
// 程序代码
}catch(Exception e1){
// catch块
}
代码实例1
public static void main(String[] args){
// 捕获异常
try{
int a[] = new int[2];
System.out.println("a[3]的值: " + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown: " + e);
}
System.out.println("Out of the block!");
}
输出结果1
(二)多重捕获块
多重捕获块,一个try代码块后面跟随多个catch代码块的情况。
可在try语句后添加多个catch块。
若保护代码中发生异常,异常被抛给第一个catch块,若抛出异常的数据类型与ExceptionType1匹配,它在这里被捕获;若不匹配,则会被传递给第二个catch块。
try/catch...catch 语法
// 多重捕获块
try{
// 程序代码
}catch(异常类型1 e1){
// catch块
}catch(异常类型2 e2){
// catch块
}catch(异常类型3 e3){
// catch块
}
代码实例2
// 多重捕获块
try{
file = new FileInputStream(filename);
x = (byte) file.read();
}catch(FileNotFoundException f){
f.printStackTrace();
return -1;
}catch(IOException i){
i.printStackTrace();
return -1;
}
(三)throw/throws关键字
- throw关键字:在指定方法中抛出指定的异常;
- throws关键字:异常处理的第一种方式,交给别人处理作用。
若一个方法没有捕获到一个检查性异常,则该方法必须使用throws关键字来声明,throws关键字放在方法签名的尾部。也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
// throw/throws
public void deposit(double amount) throws RemoteException{
throw new RemoteException();
}
public void withdraw(double amount) throws RemoteException, ArrayIndexOutOfBoundsException{
}
(四)finall关键字
finally关键字用来创建在try代码块后面执行的模块;
无论是否发生异常,finally代码块中的代码总会被执行;
在finally代码块中,可运行清理类型等收尾善后性质的语句。
finally语法如下:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
代码实例3
// finally
int a[] = new int[2];
try{
System.out.println("a[3]的值: " + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown: " + e);
}finally{
a[0] = 6;
System.out.println("First element value: " +a[0]);
System.out.println("The finally statement is executed");
}
System.out.println("Out of the block!");
输出结果3
注:
- catch不能独立于try存在;
- 在try/catch后面finally并非必须添加;
- try代码块不能既没 catch 块也没 finally 块;
- try, catch, finally 块之间不能添加任何代码。
四、自定义异常
Java的异常机制中定义的所有异常不可能预见所有可能出现的错误,因此需要创建自己的异常。
自定义异常需满足以下条件:
- 所有异常必须是Throwable的子类;
- 检查性异常类,继承Exception类;
- 运行时异常类,继承RuntimeException类。