异常
运行时异常:
都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
非运行时异常(编译异常):
是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。如IOException、SQLException等
throw:
如果代码可能会引发某种错误,可以创建一个合适的异常类实例并抛出它,这就是抛出异常。
throws:
在Java中,当前执行的语句必属于某个方法,Java解释器调用main方法执行开始执行程序。若方法中存在检查异常,如果不对其捕获,那必须在方法头中显式声明该异常,以便于告知方法调用者此方法有异常,需要进行处理。 在方法中声明一个异常,方法头中使用关键字throws,后面接上要声明的异常。若声明多个异常,则使用逗号分割。
try-catch底层?
class字节码指令中会有异常表,表示哪一行到哪一行的代码可能有什么异常:


- from 可能发生异常的起始点
- to 可能发生异常的结束点
- target 上述from和to之前发生异常后的异常处理者的位置
- type 异常处理者处理的异常的类信息
什么时候不走finally?
try或catch中进入了死循环
虚拟机退出
守护线程中可能不会走finally就被回收了
finally的执行顺序
finally正常情况下都会被执行的
如果finally里有return语句,那么它就是整个try-catch-finally结构的返回结果
若没有,就得看try or catch里的return语句了
程序出现了异常会发生什么?
运行时异常:
- 被try-catch捕获:JVM会将异常对象交给对应的catch处理,异常不会向上抛出(catch块中没有继续抛),处理完后,线程仍然继续执行代码
- 在方法声明上被抛出:交给上一级的方法进行处理,直到找到能处理该异常的catch块,但运行时异常一般没必要写方法声明上抛出,因为不写同时也不对其try-catch捕获的话,默认就是向上一级方法抛出
- 无法被处理:没有相应catch块处理,该异常会被交给线程的异常处理器,如果没设置异常处理器,那就走JVM默认的异常处理器,即线程终止,标准输出打印信息,即使有了异常处理器去处理,在处理器处理完后,抛异常的线程仍然会被终止,所以想让线程抛异常后还能继续执行下去,只能用try-catch捕捉异常
非运行时异常:
在编译时就必须被处理,所以和运行时异常走一样的逻辑
如何设置异常处理器?
为特定线程设置处理器:
1 | Thread thread = new Thread(() -> { |
案例:
异常被捕获,仍然执行代码,抛异常之前的代码都能正常执行:
打印:线程仍然执行,i = 10,b = 9
定义异常处理器处理异常:
打印:
OutOfMemoryError
StackOverflowError
NoClassDefFoundError
