一、什么是异常?
正常程序所不能处理或没有处理的不正常行为称为异常。Java异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序健壮性。
二、异常的层次结构
三、异常的分类
1.Throwable
异常体系的顶层类,其派生出两个重要的子类, Error 和 Exception
2.Error
非程序异常,即程序不能捕获的异常,一般是编译或者系统性的错误,比如:JVM的内部错误、资源耗尽等,典型代表: Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)、OutOfMemoryError:内存不足错误、StackOverflowError:栈溢出错误
3.Exception
程序本身可以捕获并且可以处理的异常,Exception 这种异常又分为两类:运行时异常和编译时异常。
- 运行时异常
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
异常 | 异常名称 |
空指针异常 | NullPointerException |
类型转换异常 | ClassCastException |
算术异常 | ArithmeticException |
非法的参数异常 | IllegalArgumentException |
数字格式化异常 | NubmerFormatException |
非法状态异常 | IllegalStateException |
下标越界异常 | IndexOutOfBoundsException |
数组下标越界异常 | ArrayIndexOutOfBoundsException |
字符串下标越界异常 | StringIndexOutOfBoundsException |
没有这样的元素异常 | NoSuchElementException |
输入类型不匹配异常 | InputMisMatchException |
- 编译异常
异常 | 异常名称 |
输入\输出异常 | IOException |
文件未找到异常 | FileNotFoundException |
EOF异常 | EOFException |
格式错误的 URL 异常 | MalformedURLException |
未知主机异常 | UnknownHostException |
SQL异常 | SQLException |
不支持克隆异常 | CloneNotSupportedException |
反射操作异常 | ReflectiveOperationException |
类未找到异常 | ClassNotFoundException |
四、异常的检查
1.可查异常
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。
2.不可查异常
包括运行时异常(RuntimeException与其子类)和错误(Error)。
五、异常关键字
- try – 用于监听。将可能抛出异常的代码放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
- catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
- finally – finally语句块总是会被执行。它主要用于回收在try块里打开的资源(如数据库连接、网络连接和磁盘文件)。只有finally块执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
- throw – 用于抛出异常。
- throws – 用在方法签名中,用于声明该方法可能抛出的异常。
六、异常的处理
1.声明异常(throws)
若方法中存在检查异常,如果不对其捕获,那必须在方法头中显式声明该异常,以便于告知方法调用者此方法有异常,需要进行处理。 在方法中声明一个异常,方法头中使用关键字throws,后面接上要声明的异常。若声明多个异常,则使用逗号分割。如下所示:
public static void method() throws IOException, FileNotFoundException{
//something statements
}
2.抛出异常(throw)
如果代码可能会引发某种错误,可以创建一个合适的异常类实例并抛出它,这就是抛出异常。如下所示:
public static double method(int value) {
if(value == 0) {
throw new ArithmeticException("参数不能为0"); //抛出一个运行时异常
}
return 5.0 / value;
}
3.try-catch 捕获异常
throws对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理,如果真正要对异常进行处理,就需要try-catch。
try{
// 可能会发生异常的代码
}catch(异常类型 e){
// 对捕获到的异常进行处理
}finally{
// 此处的语句无论是否发生异常,都会被执行到
}
// 如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行
七、自定义异常
Java 虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常,此时就需要维护符合我们实际情况的异常结构,就需要自定义异常。
public class MyException extends Exception {
public MyException(){ }
public MyException(String msg){
super(msg);
}
// ...
}
public class MyClass {
public void myMethod() throws MyException {
// 假设这是一个条件检查
if (/* 某些条件不满足 */) {
throw new MyException("发生了自定义异常");
}
// 正常的方法逻辑
}
}
八、异常注意点
- try、catch和finally都不能单独使用,只能是try-catch、try-finally或者try-catch-finally。
- try语句块监控代码,出现异常就停止执行下面的代码,然后将异常移交给catch语句块来处理。
- finally语句块中的代码一定会被执行,常用于回收资源 。
- throws:声明一个异常,告知方法调用者。
- throw :抛出一个异常,至于该异常被捕获还是继续抛出都与它无关。
九、常见异常
-
RuntimeException
- java.lang.ArrayIndexOutOfBoundsException 数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
- java.lang.ArithmeticException 算术条件异常。譬如:整数除零等。
- java.lang.NullPointerException 空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
- java.lang.ClassNotFoundException 找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
- java.lang.NegativeArraySizeException 数组长度为负异常
- java.lang.ArrayStoreException 数组中包含不兼容的值抛出的异常
- java.lang.SecurityException 安全性异常
- java.lang.IllegalArgumentException 非法参数异常
-
IOException
- IOException:操作输入流和输出流时可能出现的异常。
- EOFException 文件已结束异常
- FileNotFoundException 文件未找到异常
-
其他
- ClassCastException 类型转换异常类
- ArrayStoreException 数组中包含不兼容的值抛出的异常
- SQLException 操作数据库异常类
- NoSuchFieldException 字段未找到异常
- NoSuchMethodException 方法未找到抛出的异常
- NumberFormatException 字符串转换为数字抛出的异常
- StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
- IllegalAccessException 不允许访问某类异常
- InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常