异常的处理
1、抛出异常
·显示的 throw 抛出异常
·JVM遇到异常状态时,隐式的抛出异常
2、捕获异常涉及代码块
·try代码块:用来标记需要进行异常监控的代码
·catch代码块:定义针对 catch() 内的异 常类型的 异常处理器,由于处理异常时至上而下匹配异常表!故catch内的异常类型不可覆盖后边的!支持多异常catch(xx | xx)检测
·finally代码块:声明一段必定允许的代码!会定义一个 any的异常处理器 监控try catch整个区域
异常基本概念
·本质:程序控制权的一种即时的,非局部的转换———从异常抛出的地方转换到处理异常的地方
·原理:一切异常都是Throwable的子类
Error为不可捕获的异常unchecked exception
Exception的子类 RuntimeException为程序虽然无法继续但是还可以抢救一下(不经常发生)的异常unchecked exception, 其他子类均为 必须捕获且处理的异常checked exception。
checked exception 需要显示地捕获,或者throws 标注,以便最大化利用java编译器的编译时检查
unchecked exception 虽然不被编译器检测,但会检测 手动抛出的unchecked exception
·异常实例的构造代价非常大,因为需要生成栈轨迹等等!
1、如何捕获异常?
·关于异常器:当生成字节码后,每个方法都具备0 或 多个异常处理器,异常表内的每个条目代表一个异常处理器,表格可以表示台条目的顺序, 控制范围, 异常类型等等!(表格顺序是由class文件定义的)使用javap对含有异常的源码进行反编译, 可以查看异常表
·捕获过程:当程序触发异常时,JVM会自上而下的遍历搜索异常表内条目,逐一对照1. 是否在其监控范围 2,异常类型是否相同! 如果无匹配条目,java栈出栈恢复到调用方法内,在调用者身上遍历异常表, 如果到了栈低仍无匹配条目,这整个执行线程将被禁止!
2、finally
·finally只可以和 try 配合使用
·为什么finally总是可以执行?
复制finally内语句,放到try-catch语句正常执行路径以及异常执行路径的出口中。
使用javap -c 反汇编包含finally语句代码 会 看到有三个finlly代码块
针对异常处理路径可能处理try-catch整个代码块内的任何一个异常,所以java编译器会生成一个或多个any类型的异常处理器用来监控整个try-catch区域,该条目target会指向另一份复制的finally代码块,java编译器会重新抛出所捕获的异常
·如果catch有return话,是否执行finally内语句? 执行,但是不影响 return 语句返回的值! java思想 1. 后面的语句不可以影响前面的语句! 2. return 存在就是是方法的最后执行的语句
3、异常屏蔽?
·比如: 就是当 某方法 throws XxxException 后,连续进行 throw XXXException(); 最终该方法只会抛出 最后throw的异常 除非在最后显示throw之前存在隐式throw运行时异常!最终throw该隐式异常!
·如果解决前面显示throw的异常被屏蔽呢?
遇到异常就使用 try-catch 进行抛出!不要继续向上抛!
使用 addSuppressed(lastException) 将之前的异常信息和新异常合并!
4、try-with-resource 语法糖
·自动进行流的关闭!
·程序可以在 try 关键字后声明并实例化实现了 AutoCloseable 接口的类
try(new xx(); new xx()??{ xxxxx}catch{}finally{}
·try-with-resource底层使用addSuppressed()!
·反编译:
就是编译器把苦活给干了!
源码:
public class Foo implements AutoCloseable { private final String name; public Foo(String name) { this.name = name; } @Override public void close() { throw new RuntimeException(name); } public static void main(String[] args) { try (Foo foo0 = new Foo("Foo0"); Foo foo1 = new Foo("Foo1"); Foo foo2 = new Foo("Foo2")) { int a = 100; } } } |
反编译文件:
// Decompiled by DJ v3.12.12.96 Copyright 2011 Atanas Neshkov Date: 8/10/2020 4:56:47 PM // Home Page: http://members.fortunecity.com/neshkov/dj.html http://www.neshkov.com/dj.html - Check often for new version! // Decompiler options: packimports(3) // Source File Name: Foo.java public class Foo implements AutoCloseable { public Foo(String s) { name = s; } public void close() { throw new RuntimeException(name); } public static void main(String args[]) { Foo foo = new Foo("Foo0"); try { Foo foo1 = new Foo("Foo1"); try { Foo foo2 = new Foo("Foo2"); byte byte0; try { byte0 = 100; } catch(Throwable throwable3) { try { foo2.close(); } catch(Throwable throwable5) { throwable3.addSuppressed(throwable5); } throw throwable3; } foo2.close(); } catch(Throwable throwable1) { try { foo1.close(); } catch(Throwable throwable4) { throwable1.addSuppressed(throwable4); } throw throwable1; } foo1.close(); } catch(Throwable throwable) { try { foo.close(); } catch(Throwable throwable2) { throwable.addSuppressed(throwable2); } throw throwable; } foo.close(); } private final String name; } |