try/catch
异常(Exception)是平日里写代码过程中很常见的,可以分为运行时异常(RuntimeException)和非运行时异常(也叫编译异常)。运行时异常一般是程序逻辑错误引起的,可以选择进行try/catch捕获处理,也可以不处理;编译异常则必须要try/catch进行捕获,否则不能通过编译。当然今天的重点不在异常的讲解,而是由异常引出try/catch。
说到try/catch自然而然的就会联想到finally,因为finally代码块必须与 try 或 try/catch 代码块配合使用。不管try代码块中的代码是否发生异常,finally代码块中的代码都会执行。
try/catch…finally遇上return
记得之前面试的时候,遇到这样一个问题:有一个方法,代码有try/catch包裹,该方法是有返回值的,问finally代码块和return哪个先执行。现在就来通过简单代码示例看一下到底谁先执行。
我用简单的代码模拟了一下问题的情景,代码如下:
- 无异常情况:
public class Test {
public static void main(String[] args) {
System.out.println("i=" + new Test().test());
}
public int test() {
int i = 1;
try {
i++;// i=2
System.out.println("try...");
return i;
} catch (Exception e) {
i++;
System.out.println("catch...");
} finally {
i++;//i=3
System.out.println("finally...");
}
return i;
}
}
程序执行结果如下:
try…
finally…
i=2
执行try代码块,此时的i=2,这段代码没有异常发生,所以没有执行catch代码块中的代码(这也验证了不发生异常的情况下,finally代码块也会执行)。从执行结果可以看出return后i=2,说明return在finally之前执行的。
通过打断点调试,也验证了这个结论:
此时i=2且执行了return,继续向下执行进入finally代码块:
最终打印结果i=2。
- 发生异常情况:
public class Test {
public static void main(String[] args) {
System.out.println("i=" + new Test().test());
}
public int test() {
int i = 1;
try {
i++;//i=2
System.out.println("try...");
i = i/0;//除数为0,发生异常
return i;
} catch (Exception e) {
i++;//i=3
System.out.println("catch...");
} finally {
i++;//i=4
System.out.println("finally...");
}
return i;
}
}
运行结果如下:
try…
catch…
finally…
i=4
执行try代码块,此时的i=2,这段代码发生异常,所以执行catch代码块,此时i=3,然后执行finally代码块,此时i=4,最后执行return,返回i=4。这种情况下return在finally之后。
打断点调试如下:
发生异常,执行完finally代码块i=4,继续向下执行:
return返回i=4。
发生异常还有一种情况,return语句存在于catch代码块中,代码如下:
public class Test {
public static void main(String[] args) {
System.out.println("i=" + new Test().test());
}
public int test() {
int i = 1;
try {
i++;//i=2
System.out.println("try...");
i = i/0;//除数为0,发生异常
return i;
} catch (Exception e) {
i++;//i=3
System.out.println("catch...");
return i;
} finally {
i++;//i=4
System.out.println("finally...");
}
}
}
运行结果如下:
try…
catch…
finally…
i=3
执行try 代码块后i=2,发生异常,执行catch代码块,此时i=3,然后return返回3,最后执行finally代码块。
打断点调试如下:
发生异常,执行catch代码块并返回return,继续执行finally:
总结
没有异常发生,先执行try代码块里面的return,然后执行finally;
当有异常发生,不执行try代码块里面的return,
-return在try/catch以外时,finally在return前执行。
-catch里有return时,return在finally前执行;