异常概念
异常发生的原因
用户输入非法数据
要打开的文件不存在
网络中断/JVM内存溢出(JVM是JRE的一部分。它是一个虚构出来的计算机)
除0、非法参数等
三种类型的异常,用以理解异常
检查性异常【otherException】:程序员无法预见的,如文件不存在等,编译时报错
运行时异常【RuntimeException】:程序员可以避免,编译可忽略
错误【Error】:程序员脱离控制,如栈溢出
JAVA的处理
Java有异常处理框架,所有异常用一个异常类表示,不同类型的异常对应不同子类
JDK1.4后,异常链机制,可跟踪异常
异常体系结构
异常之间的区别和联系
Error
与编码者所执行的操作无关,也不应该试图去处理。如虚拟机运行错误Virtual MachineError,内存不够OutOfMemoryError,类定义错误NoClassDefFoundErro,链接错误LinkageError等。
===> 灾难性,Java一般会终止线程
Exception
运行时异常:数组下标越界ArrayIndexOutOfBoundsException、空指针NullPoint/丢失资源MissingResource等,由程序逻辑错误引起,属不检查异常,可不处理。
非运行时异常:必须处理,IOException, SQLException,用户自定义的Exception等。属于检查异常。
===>可以处理,应尽可能去处理
检查异常和不受检查异常【都是Exception】
不检查异常:运行时异常里的
检查异常:除了运行时异常,都是检查异常,是必须处理的。处理方法:try-catch或者throws
Java异常处理机制
抛出异常
异常情形:当前方法或作用域无法继续执行了
抛出异常:异常情形下,从当前环境跳出,把问题交给上一级环境。
抛出异常后,在堆上new一个异常对象,当前执行路径被终止且弹出对异常对象的引用。异常处理机制接管程序,从异常处理程序开始执行程序。异常处理机制将程序回复/换种方式/继续运行下去。
捕获异常
方法抛出异常后,系统寻找合适的异常处理器。
潜在的异常处理器,是异常发生时,存留在调用栈的方法的集合。
若未找到,Java程序结束。
异常处理五个关键字
try 监听: try语句块发生异常,则异常抛出
catch 捕获
finally 回收try打开的物力资源(数据库连接、网络连接、磁盘文件)如果finally里使用了return/throw等,则不会再执行try/catch中的return/throw
throw 抛出异常
throws 声明该方法会抛出异常
处理异常
try-catch
例子
写了try-catch,程序可以正常运行了,不然编译不通过
public static void main(String[] args) {
int a =1;
int b = 0;
try {
if(b == 0) throw new ArithmeticException(); // 抛出算术异常
System.out.println("a / b = " + a/b);
}catch (ArithmeticException e){
System.out.println("捕获到了异常!" + e);
}
System.out.println("程序结束");
}
这个算术异常是运行时异常,系统会自动抛出的。比如不写这个try-catch,就会:
多重catch
将捕获底层异常类的catch子句放在前面,较高层的放在后面
嵌套try
没进入一个try,异常的前后关系会被推入堆栈。如果内部不含异常,堆栈弹出,检查下一个try。
throw
异常由两个构造方法,一个有参数的,一个没有参数的。可以把参数传进去,通过e.getMessage()来获取这个异常参数。
public static void main(String[] args) {
try {
proc();
}catch (NullPointerException e){
System.out.println("main中的catch" + e);
}
}
static void proc(){
try{
// throw 明确异常
throw new NullPointerException("demo");
}catch(NullPointerException e){
// 如果用 e.getMessage() , 则可以返回“demo”这个词
System.out.println("proc中的catch" + e);
throw e; // 把异常抛出方法外
}
}
throws
在方法声明中包含throws子句,就可以不用在方法中处理了。但调用该方法的main()需要写try-catch来处理。
public static void main(String[] args) {
try {
proc();
} catch (IllegalAccessException e) {
// 如果这样throw出去,console中会由红字异常报出
//throw new RuntimeException(e);
System.out.println("main中捕获咯");
}
}
static void proc() throws IllegalAccessException{
System.out.println("Proc()中的代码");
throw new IllegalAccessException("demo"); // 是new这个异常哦
}
注意点:
Error和RuntimeException, 可以不抛出,编译通过,运行是会被系统抛出
如果是可查异常,必须在方法里写throws,然后用try-catch捕获/throws抛出
抛出异常,方法调用者必须处理,或继续抛出
调用方法必须遵循可查异常的处理和声明规则。覆盖一个方法时,不能声明与覆盖方法不同的异常。
finally
在try/catch完成后,另一个try/catch之前执行。无论有无异常都会执行。可用来释放占用的资源,一定要释放哦!
static void proc(){
System.out.println("Proc()中的代码");
int a = 2;
try{
if(a == 3){
throw new IllegalAccessException("demo"); // 是new这个异常哦
}
}catch(IllegalAccessException e) {
System.out.println(e.getMessage());
}finally {
System.out.println("finally!!! 我执行了!");
}
}
执行顺序
try, catch, 给返回值赋值
finally
return
自定义异常
继承Exception类即可,创建自定义异常
方法中抛出: try-catch捕获处理或者在方法声明里throws、调用者中捕获并处理