1.try...catch...finally块中的finally是否一定会执行?
- try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。
- 在try块中有System.exit(0)这样的语句,System.exit(0);是终止Java虚拟机JVM的,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。
2.那finally在try-catch的return的之前还是之后执行?
(1)finally语句是在try的return语句执行之后,return返回之前执行。
public class MyClass {
public static void main(String[] args) {
System.out.println(testReturn());
}
public static String testReturn() {
try {
System.out.println("try block");
return testStatement();
} finally {
System.out.println("finally block");
}
}
public static String testStatement() {
System.out.println("testStatement block");
return "after return";
}
}
运行结果为:
try block
testStatement block
finally block
after return
可以看到,try中的return语句先执行了,输出“testStatement”。但并没有立即返回,等到finally执行结束后,再进行返回输出“after return”。那当finally也有return的时候又是怎样的呢?
(2)finally如果有return语句,则会覆盖try(或catch)中的return语句;如果没有,对于原来的返回值,finally可以修引用所对应的对象,无法改变基本类型。
public class MyClass {
public static void main(String[] args) {
System.out.println("testObject: "+testObject());
System.out.println("testPrimitive: x="+testPrimitive());
}
public static Student testObject() {
Student result = new Student("Tom", 0);
try {
result.setAge(1);
return result;
} catch (Exception e) {
result.setAge(2);
return result;
} finally {
result.setAge(3); //引用类型的返回值,可被修改
// return new Student("Kobe", 33); //可以被“具体值”覆盖
}
}
public static int testPrimitive() {
int x = 0;
try {
return x=1;
} catch (Exception e) {
x = 2;
return x;
} finally {
x = 3; //基本类型的返回值,不可被修改
// return 3; //可以被“具体值”覆盖
}
}
private static class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public void setAge(int age) {
this.age = age;
}
}
}
给出下finally中没有return的情况的结果:
testObject: Student [name=Tom, age=3]
testPrimitive: x=1
在finally没有return的情况下,对于基本类型x=1的值,finally中的x=3并没有起作用;而为引用时,finally中result.setAge(3)起作用了。
(3)异常发生时,try中的return语句不会被执行,catch中的return的执行情况与try中return的执行情况一样。
public class MyClass {
public static void main(String[] args) {
System.out.println("x = "+testCatch());
}
public static int testCatch() {
int x = 20;
try {
System.out.println("try block");
x = x /0;
return x += 80;
} catch (Exception e) {
System.out.println("catch block");
return x += 15;
} finally {
System.out.println("finally block");
if (x > 25) {
System.out.println("x > 25, x = " + x);
}
x += 50;
}
}
}
运行结果:
try block
catch block
finally block
x>25, x = 35
x = 35
try中发生异常后,try中的return没有执行,而是先执行catch中的return,确定了返回值后再去执行finally块,执行完了catch再返回,finally里对x的改变对返回值无影响,原因同前面一样,也就是说情况与try中的return语句执行情况一样。
【====总结====】
执行时机问题。finally总会执行(除非是System.exit()),正常情况下在try后执行,抛异常时在catch后面执行。
返回值问题。 可以认为try(或catch)中的return语句的返回值放入线程栈的顶部:如果返回值是基本类型则顶部存放的就是值,如果返回值是引用类型,则顶部存放的是引用。 return的时候是复制了一个变量然后返回,所以之后finally操作的变量如果是基本类型的话不会改变其返回值, 但如果返回值是引用类型的话,因为指向同一个对象,就会改变其返回值。但不管是基本类型还是引用类型,都可以被finally返回的“具体值”具体值覆盖。
网友评论