1 参考资料
- https://blog.csdn.net/hguisu/article/details/6155636
- Java 编程思想(第4版) 12章
- https://www.cnblogs.com/pcheng/p/10968841.html return 的坑
- https://blog.csdn.net/sinat_22594643/article/details/80509266 return 原理
2 Java中异常的结构
(经典的一张图)
从上面的一张图可以看出,Throwable是所有异常的基类。
Error 是程序错误,编译期就无法通过。也无需程序员去手动检查。
Exception是异常,可以分为运行时异常和非运行时异常。
其中,除了RuntimeException及其子类以外,都是可检查异常(checked exception)。也就是我们需要在程序中进行处理的异常。
常见异常
3 try-catch-finally
try语句块中用于处理可能会抛出异常的程序代码。
catch语句块中用于处理try中发生异常后的处理代码
finally语句块无论异常是否发生,都会执行,因此可以用来做一些资源回收的动作。比如数据库连接池的关闭等。
try{
// 程序代码1
// 程序代码2
// 抛出异常 1
// 程序代码3 抛出异常1后,3不会执行
}catch(异常类型1 异常的变量名1){
// 处理异常1
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
finally中的一个小坑,当finally和catch中都有return语句时,返回的值可能不是你预料中的
先了解下return语句在虚拟机中实现原理:
我们知道Java方法是在Java虚拟机栈中的栈帧执行,栈帧是线程私有栈的单位,执行方法的线程会为每一个方法分配一小块栈空间来作为该方法执行时的内存空间。栈帧有
- 操作数栈
- 局部变量区
- 字节码指令区
return 返回的就是操作数栈顶部的值。但是操作数栈顶部的值往往是局部变量表中某个值的一个副本。
所以,举个例子
return x
当x是一个基本变量时(如int),它的一个副本会被复制到操作数栈。return返回这个副本,在其他地方对x进行了修改不会影响副本的值。
当x是一个引用时,在其他地方对x进行了修改,会影响返回值
写个小测试代码
import java.util.Date;
public class test {
public volatile int a =3;
public static void main(String[] args) {
System.out.println("return-result "+test());
}
public static int test(){
int i = 1;
try{
i++;
System.out.println("try:"+i);
i= i/0;
}catch (Exception e){
i++;
System.out.println("catch:"+i);
return i;
}finally {
i++;
System.out.println("finally:"+i);
//return i;
}
return 0;
}
}
结果
小结:
1、finally中的代码总会被执行。
2、当try、catch中有return时,也会执行finally。return的时候,要注意返回值的类型,是否受到finally中代码的影响。
3、finally中有return时,会直接在finally中退出,导致try、catch中的return失效。