一、try catch finally执行顺序
try{
//代码执行区域
}catch(Exception e){
//异常处理区域
}finally {
//无论如何,都会执行的代码块
}
场景一
多数场景
try {
System.out.println("try");
} catch (Exception e) {
System.out.println("catch");
} finally {
System.out.println("finally");
}
则输出结果为:
try
finally
场景二
当try中有返回值,finally中没有返回值,try中不抛出异常,则执行顺序为:
try --> finally --> try的返回值
String test() {
try {
System.out.println("这里是try");
return "try 返回值";
}finally {
System.out.println("这里是finally");
}
}
输出结果为:
这里是try
这里是finally
try 返回值
场景三
String ttt = "test1"
try{
return ttt;
}finally{
ttt = "test2"
}
输出结果为:
test1
也就是说在finally中无法修改返回值
场景四
public class Test {
public static void main(String[] args) throws Exception{
System.out.println(new Test().test());
}
int test() {
try {
return func1();
}finally {
return func2();
}
}
int func1() {
System.out.println("func1");
return 1;
}
int func2() {
System.out.println("func2");
return 2;
}
}
输出结果为:
func1
func2
2
能看出来,此时try中的return似乎没有生效。但实际上不是被覆盖,而是执行顺序变更导致的。
也就是先执行:
try -> 执行计算return的值 -> 跳转到finally -> 返回try中的return 。
如果finally中有return语句也就不会执行最后一步了,看起来像是try的返回值被覆盖了,实际上不是被覆盖,而是执行顺序变更导致的。
可以看出:
语句按顺序执行,遇到return,会进去执行其中的方法语句,执行到遇到return为止,然后跳到finally语句中输出,再return最后调用得到的数据。
官方jvm规范说明如下:
如果try语句里有return,那么代码的行为如下:
1、如果有返回值,就把返回值保存至局部变量中;
2、执行jsr指令跳到finally语句里执行;
3、执行完finally语句后,返回之前保存在局部变量里的值
总结:
1、不管有没有异常,finally中的语句总会执行
2、try/catch中有返回值,finally中的语句依然会继续执行
3、try、catch、finally语句中,如果只有try语句中有return返回值,此后在catch、finally中对变量做任何修改,都不影响try中return的返回值;
4、finally是在return后面的表达式运算之后执行的,此时并没有返回运算后的值,而是把值保存起来,不管finally对该值做任何改变,返回的值都不会改变,依然返回保存起来的值,也就是说方法的返回值是在finally运算之前就确定了的;
5、try、catch中有返回值,而try中抛出的异常恰好与catch中的异常匹配,则返回catch中的return值;
6、如果finally块中有return语句,则返回finally中的返回值,try或catch中的返回语句忽略;
7、finally中最好不要包含return,程序会提前退出,也就是说返回的值不是try或catch中的值,finally语句的返回值会屏蔽try或catch的返回值
8、如果finally块中抛出异常,则整个try、catch、finally块中抛出异常,且没有返回值
二、Java异常
Java异常实际上是Throwable子类的实例化对象,Throwable有两个重要的子类:Exception和Error。
java.lang.object
|–java.lang.Throwable
|-- |-- java.lang.Error
|-- |-- java.lang.Exception
Error
一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。
Exception
表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。
Exception类又分为:
- 运行时异常(Runtime Exception):运行时异常ArithmaticException,IllegalArgumentException,编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。
- 受检查的异常(Checked Exception ):而受检查的异常,要么用try catch捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。
常见的运行时异常:
异常 | 描述 |
---|---|
ArrayIndexOutOfBoundsException | 数组下标越界异常 |
ArithmaticException | 算数异常 如除数为零 |
NullPointerException | 空指针异常 |
IllegalArgumentException | 不合法参数异常 |