在网上看到一些异常处理的面试题,试着总结一下,先看下面代码,把这个方法在main中进行调用打印返回结果,看看结果输出什么。

public static  int testBasic(){
int i = 1;
try{
i++;
System.out.println("try block, i = "+i);
}catch(Exception e){
i ++;
System.out.println("catch block i = "+i);
}finally{
i = 10;
System.out.println("finally block i = "+i);
}
return i;
}

没错,会按照顺序执行,先执行try内代码段,没有异常的话进入finally,最后返回,那么输出如下:

try block, i = 2
finally block i = 10
main test i = 10

这个没有问题,如果我们把return语句放入try catch里又会怎么样呢

public static  int testBasic(){
int i = 1;
try{
i++;
System.out.println("try block, i = "+i);
return i;
}catch(Exception e){
i ++;
System.out.println("catch block i = "+i);
return i;
}finally{
i = 10;
System.out.println("finally block i = "+i);
}
}

输出结果是:

try block, i = 2
finally block i = 10
main test i = 2

代码顺序执行从try到finally,由于finally是无论如何都会执行的,所以try里的语句并不会直接返回。在try语句的return块中,return返回的引用变量并不是try语句外定义的引用变量i,而是系统重新定义了一个局部引用i’,这个引用指向了引用i对应的值,也就是2,即使在finally语句中把引用i指向了值10,因为return返回的引用已经不是i,而是i',所以引用i的值和try语句中的返回值无关了。

但是,这只是一部分,如果把i换成包装类型而不是基本类型呢,来看看输出结果怎样,示例如下:

public static  List<Object> testWrap(){
List<Object> list = new ArrayList<>();
try{
list.add("try");
System.out.println("try block");
return list;
}catch(Exception e){
list.add("catch");
System.out.println("catch block");
return list;
}finally{
list.add("finally");
System.out.println("finally block ");
}
}

打印结果如下:

try block
finally block
main test i = [try, finally]

可以看到,finally里对list集合的操作生效了,这是为什么呢。我们知道基本类型在栈中存储,而对于非基本类型是存储在堆中的,返回的是堆中的地址,因此内容被改变了。

好了,现在我们在finally里加一个return,看看语句是从哪里返回的。

public static  int testBasic(){
int i = 1;
try{
i++;
System.out.println("try block, i = "+i);
return i;
}catch(Exception e){
i ++;
System.out.println("catch block i = "+i);
return i;
}finally{
i = 10;
System.out.println("finally block i = "+i);
return i;
}
}

输出结果如下:

try block, i = 2
finally block i = 10
main test i = 10

可以看到,是从finally语句块中返回的。可见,JVM是忽略了try中的return语句。但IDE中会对finally中加的return有黄色警告提示,这是为什么呢,在try里加入一行会执行异常的代码,如下:

public static  int testBasic(){
int i = 1;
try{
i++;
int m = i / 0 ;
System.out.println("try block, i = "+i);
return i;
}catch(Exception e){
i ++;
System.out.println("catch block i = "+i);
return i;
}finally{
i = 10;
System.out.println("finally block i = "+i);
return i;
}
}

打印结果如下:

catch block i = 3
finally block i = 10
main test i = 10

可以看到,因为finally中有return语句,try、catch中的异常被消化掉了,屏蔽了异常的发生,这与初期使用try、catch的初衷是相违背的,因此编译器也会提示警告。

那如果在finally中有异常发生,会对try、catch中的异常有什么影响呢?

public static  int testBasic(){
int i = 1;
try{
i++;
Integer.parseInt(null);
System.out.println("try block, i = "+i);
return i;
}catch(Exception e){
String.valueOf(null);
System.out.println("catch block i = "+i);
return i;
}finally{
i = 10;
int m = i / 0;
System.out.println("finally block i = "+i);
}
}

这里我们在try、catch里强行加上异常语句,打印结果如下:

Exception in thread "main" java.lang.ArithmeticException: / by zero
at tryandcatch.TryAndCatch.testBasic(TryAndCatch.java:25)
at tryandcatch.TryAndCatch.main(TryAndCatch.java:45)

这个提示表示的是finally里的异常信息,也就是说一旦finally里发生异常,try、catch里的异常信息即被消化掉了,也达不到异常信息处理的目的。

总结以上测试:

1、finally语句总会执行

2、如果try、catch中有return语句,finally中没有return,那么在finally中修改除包装类型和静态变量、全局变量以外的数据都不会对try、catch中返回的变量有任何的影响(包装类型、静态变量会改变、全局变量

3、尽量不要在finally中使用return语句,如果使用的话,会忽略try、catch中的返回语句,也会忽略try、catch中的异常,屏蔽了错误的发生

4、finally中避免再次抛出异常,一旦finally中发生异常,代码执行将会抛出finally中的异常信息,try、catch中的异常将被忽略

所以在实际项目中,finally常常是用来关闭流或者数据库资源的,并不额外做其他操作。

try catch finally 执行顺序面试题总结的更多相关文章

  1. 异常处理 try...catch...finally 执行顺序, 以及对返回值得影响

    异常处理 try...catch...finally 执行顺序, 以及对返回值得影响 结论:1.不管有没有出现异常,finally块中代码都会执行:2.当try和catch中有return时,fina ...

  2. Promise和setTimeout执行顺序 面试题

    看到过下面这样一道题: (function test() { setTimeout(function() {console.log(4)}, 0); new Promise(function exec ...

  3. try catch finally执行顺序

    1.不管有木有出现异常,finally块中代码都会执行: 2.当try和catch中有return时,finally仍然会执行: 3.finally是在return表达式运算后前执行的,所以函数返回值 ...

  4. try..catch..finally执行顺序return

    try..catch..finally这个语法大家都很熟悉,就是捕捉异常.处理异常,面试中经常被问到的一个问题是:如果在try...catch中的某某地方return了,那么之后的某某步骤还会不会执行 ...

  5. JAVA代码中加了Try...Catch的执行顺序

    public static String getString(){ try { //return "a" + 1/0; return "a"; } catch ...

  6. try catch finally执行顺序 (return / 变量覆盖)

    finally有return 始终返回finally中的return 抛弃 try 与catch中的return 情况1:try{} catch(){}finally{} return x; try{ ...

  7. try,catch,finally含return时的执行顺序及丢失的伪例

    最近面试遇到一个之前也看到过但没去看一下的问题.就是有return情况下的try,catch,finally的执行顺序. 今天写了下. 先看顺序问题.总结如下: 一:finally中没有写return ...

  8. 由阿里巴巴一道笔试题看Java静态代码块、静态函数、动态代码块、构造函数等的执行顺序

    一.阿里巴巴笔试题: public class Test { public static int k = 0; public static Test t1 = new Test("t1&qu ...

  9. 【Java疑难杂症】有return的情况下try catch finally的执行顺序

    有这样一个问题,异常处理大家应该都不陌生,类似如下代码: public class Test { public static void main(String[] args) { int d1 = 0 ...

随机推荐

  1. github访问速度慢,样式加载不完全解决

    现象如下图: 解决方案: 绑定host 185.31.17.184 github.global.ssl.fastly.net

  2. UVA 10886 Standard Deviation

    https://vjudge.net/problem/UVA-10886 计算标准差 碰到这种题将式子展开 #include<cmath> #include<cstdio> / ...

  3. POJ 1014 / HDU 1059 Dividing 多重背包+二进制分解

    Problem Description Marsha and Bill own a collection of marbles. They want to split the collection a ...

  4. Bzoj1312 / POJ3155 Neerc2006 Hard Life

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 459  Solved: 114 Description 在一家公司中,人事部经理与业务部经理不和.一次 ...

  5. 【BZOJ】1774: [Usaco2009 Dec]Toll 过路费

    [题意]给定无向图,距离定义为边权和+最大点权,询问若干个两点最短距离.n<=250. [算法]排序+floyd [题解]考虑floyd的过程是每次找一个中转点,为了在当前找到一条新路径时方便地 ...

  6. Vue.js最佳实践(五招让你成为Vue.js大师)

    对大部分人来说,掌握Vue.js基本的几个API后就已经能够正常地开发前端网站.但如果你想更加高效地使用Vue来开发,成为Vue.js大师,那下面我要传授的这五招你一定得认真学习一下了. 第一招:化繁 ...

  7. application.properties 文件的优先级

    bootstrapProperties #来自configServer的值 commandLineArgs #命令行参数 servletConfigInitParams servletContextI ...

  8. 【转】gif文件格式详解

    1.概述 ~~~~~~~~ GIF(Graphics Interchange Format,图形交换格式)文件是由 CompuServe公司开发的图形文件格式,版权所有,任何商业目的使用均须 Comp ...

  9. perl6 拖库脚本

    #注入点: #https://fei.sg/shop/products.php?action=content&id=-23 #check mysql column_name of the sq ...

  10. vs 2015 插件 supercharger 破解方式

    亲测有效:效果如图 方法如下: 1.打开Supercharger的options; 2.点击Pricing & Registration 3.复制 license  然后再按Paste &am ...