结构
Throwable 异常的根父类
常用方法
printStackTrace() 打印异常的详细信息
getMessage() 获取发生异常的原因
Error Throwable的子类
java虚拟机无法解决的严重问题,jvm系统内部错误,资源耗尽等严重情况,一般不编写针对性的代码进行处理。例如StackOverflowError(栈内存溢出)OutMemoryError(java heap space)
Exception Throwable的子类
其他因编程错误或偶然的外在因素导致的一般性问题,需要编写针对性处理代码
Exception和RuntimeException区别
RuntimeException是运行时异常
编译可以通过,在运行时可能抛出,出现概率高一些,一般针对于运行时异常,都不处理
Exception是一般异常
编译不能通过,要求必须在编译之前,考虑异常的处理,不处理编译不通过
分类
编译时异常(checked异常、受检异常)
运行时异常(runtime异常、unchecked异常、非受检异常)
处理异常
方式1
// 捕获到异常之后,后面的代码可以继续执行
// 声明多个catch结构时,不同的异常类型不存在子父类关系情况下,声明顺序无所谓
// 不同的异常类型存在子父类关系情况下,必须将子类声明在父类结构的上面,否则将报错
// try中声明的变量,出了try结构之后,就不可以进行调用了
try {
// 可能产生异常的代码
} catch (异常类型1 e) { // 依次匹配可能出现的异常,匹配到之后就不会继续匹配
} catch (异常类型2 e) {
} finally { // 无法是否发生异常,都无条件执行的语句
}
System.out.println("继续执行其他代码");
finally说明
无法是否发生异常,无论try或catach中是否存在return语句等,finally中声明的代码都将执行
如果代码中执行了System.exit(0);finally中的代码将不会执行
开发中一些资源(输入流、输出流、数据库连接、socket连接等资源),在使用完后,必须显式关闭,否则GC不会自动回收这些资源,进而导致内存泄露;为了保证这些资源使用完后一定关闭,写在finally中
// 当finally中有return语句时,将返回finally中return的值
public Integer number(Integer num) {
try {
return num;
} catch (NumberFormatException e) {
return num--;
} finally {
System.out.println("结束");
return ++num;
}
}
number(10); // 11
// 如果finally中对返回值进行处理,代码中return的值是finally中处理前的值
public Integer number(Integer num) {
try {
return num;
} catch (NumberFormatException e) {
return num--;
} finally {
System.out.println("结束");
++num;
}
}
number(10);// 返回10
// 原因
// 方法是一个栈针,栈针包含局部变量表、操作岀栈
// num在局部变量表中
// 操作岀栈也是一个栈
// return的数据先临时放到操作岀栈中,return num;时已经将num=10放进操作岀栈中了
// finally执行时操作的是局部变量表,finally执行后方法结束,操作岀栈中的num返回出去了
try结构可以直接包含finally,也可以包含catch和finally;但是finally不能单独使用
try {
} finally {
}
try {
} catch() {
}
方式2
在方法的声明处,使用"throws 异常类型1,异常类型2"
public void test() throws FileNotFoundException, IoException {
}
当有其他方法调用使用了throws的方法时,必须处理异常或继承抛出异常
public void test1() throws FileNotFoundException, IoException {
test();
}
public void test2() {
try {
test();
} catch (FileNotFoundException | IoException e) {
}
}
两种方式使用场景
资源一定要被执行时,使用try-catch-finally
父类被重写方法没有throws异常类型,则子类重写方法中如果出现异常,只能考虑try-catch-finally
方法a一次调用了方法b,c,d等方法,方法b,c,d之间时递进关系,如果方法b,c,d中有异常,通常使用throws;而方法a中通常使用try-catch-finally
手动抛出异常
throw new 异常对象();
自定义异常
继承与现有的异常体系,通常继承于RuntimeException 或 Exception
通常提供几个重载的构造器
提供一个全局常量serialVersionUID,需要自定义一个值,不能与现有异常类的值相同,用于标识当前类
示例
public class MyException extends Exception {
static final long serialVersionUID = 1L;
public MyException() {
}
public MyException(String name) {
super(name);
}
public MyException(String message, Throwable cause) {
super(message, cause);
}
}
为什么使用自定义异常
通过异常的名称就能直接判断此异常出现的原因。实际开发过程中,不满足我们指定的条件时,指明我们自己特有的异常类。