Java复习的差不多了,但是怕面试挑细碎知识点问,还是集中做一个总结吧
异常
异常也是一种类型,它是JDK对“异常事件”的一种抽象。配合throw 关键字可以抛出一个异常对象,这个异常对象如果一直不能被捕获并处理,最终将会抛给JVM,JVM执行默认行为:在标准错误输出流system.err中打印堆栈信息。
所以,如果问我什么是异常,我会说:Java的异常是对非正常事件的一种抽象,具体的异常信息通常都会创建一个异常实例,用于保存这异常的元信息。
分类
异常的顶层父类是throwable。Throw关键字底层对应athrow命令,只能抛出throwable的实例。
Throwable有两大子类:
【1】error
Error一般是系统相关的错误,例如OOM、Stack Overflow等
【2】exception
异常又可以分为运行时异常runtimeException和编译期异常。
runtimeException以及它的子类都是非受检异常,无论是主动抛出这个异常还是调用了声明该异常的方法。都可以不去处理,而交给JVM去处理。JVM会调用注册在线程上未捕获异常处理器(能抛给JVM异常处理器的异常一定是运行时异常)
public static void main(String[] args) {
Thread.currentThread().setUncaughtExceptionHandler((r,e)->{
System.out.println("没事,抛者玩的");
System.out.println(r.getName()+" "+e.getMessage());
});
throw new RuntimeException();
}
通过设置异常处理器,也可以实现子线程与主线程的通信,如错误报告。
除了runtimeException以及它的子类,其他的异常(Exeption类型)都是受检异常。必须进行try-catch处理或者throws向上抛出。(当然了,如果抛给了JVM则执行默认的处理器,标准错误输出流进行输出)
常见的受检异常包括SQL异常、IO异常、文件无法找到异常、EOF异常等。
注意:Error类及其子类表示程序本身无法修复的错误,javac不会检查他们,当程序运行时出现这些异常,Java进程会直接终止——Error是非受检的。
不过Error类型一般是JDK预设好的,用户一般不会主动扩展错误类型,而用户总是选择扩展RuntimeException类型。
异常处理机制
一个异常的执行顺序:
【1】new一个异常对象
【2】中止当前正在执行的程序
【3】弹出异常对象的引用
【4】异常处理机制接管被中止的程序
【5】进入异常处理程序的catch代码块继续执行。
JVM使用**方法调用栈(method invocation stack)**来跟踪每一个线程中一系列方法的调用过程。该栈保存了每个调用方法的本地信息(如方法的局部变量)。每个线程都有一个独立的方法调用栈。Java主线程中栈底方法是main()方法。每当一个新方法被调用时,JVM将描述该方法的栈结构放入栈顶,位于栈顶的方法就是正在执行的方法。
当一个方法正常执行完毕,JVM就会从调用栈中弹出该方法的栈结构(出栈),然后继续执行栈中下一个方法。
如果在执行方法的过程中抛出了异常,则JVM必须能找到catch代码块,如果在当前方法找不到,JVM就会从调用栈中弹出该方法的栈结构,继续到下一个方法中查找合适的catch代码块。
每个方法调用栈的catch结构可以看到当前栈帧的异常处理器,如果找不到就会栈帧出栈,并寻找上一调用级别的异常处理器。最终main方法栈帧出栈后,交给JVM的未捕获异常处理器进行处理。如果没有设置则执行默认行为:
【1】调用异常对象的printStackTrace()方法,打印来自方法调用栈的异常信息
【2】如果该线程不是主线程,则终止这个线程,其他线程继续正常运行。如果是主线程,那么整个应用程序被终止。
finally
如果finally和try/catch都有返回语句,那么后者的return内容将会被覆盖掉。后者返回之前会执行finally的内容。
Finally语句不被执行的唯一情况就是:执行了system.exit()方法——用于终止当前的Java进程
如果在try和catch进行return,首先这个return的值是赋给了一个局部变量,如果finally中不存在任何return语句,那么返回的就是这个局部变量。(字面量或者引用被赋值给一个局部变量)
如果finally中存在return ,则最终返回的是finally中的return。Catch中的return X 相当于将X存放到了一个局部变量(如果X=a++也是会执行的)。
return覆盖的情况:
static int fun(){
int a =0