trycatchfinally执⾏顺序⾯试题总结
在⽹上看到⼀些异常处理的⾯试题,试着总结⼀下,先看下⾯代码,把这个⽅法在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语句中的返回值⽆关了。
jvm面试题总结及答案
但是,这只是⼀部分,如果把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 stBasic(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常常是⽤来关闭流或者数据库资源的,并不额外做其他操作。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。