众所周知,Java中异常处理机制try-catch-finally,try用来捕获异常,然后交给catch语句进行处理,finally用来替补,无论try中与catch中的遇到什么问题,fincally语句中都会被执行。
但是先给大家一个开胃菜:
public class ReturnFinally {
public static void main(String[] args) {
System.out.println(test1());
}
public static int test1() {
int b = 20;
try {
System.out.println("try");
return b += 80;
}
catch (Exception e) {
System.out.println("catch");
}
finally {
System.out.println("finally");
System.out.println("b = " + b);
}
return b;
}
}
猜猜它的运行结果。
try
finally
b = 100
100
结果如上。return 语句的主要作用是结束当前方法,同时看看有没有需要带一个参数返回一下。既然是结束当前方法,那么上面就不应该输出finally和b=100?这个足以证明,finally大部分情况都会被执行,既然是大部分,那么特例是?System.exit(0);,因为这个句话是结束JVM,既然运行环境虚拟机都关闭了,那么肯定不会走了。
再给大家来个例子,擦亮眼睛,仔细斟酌
public class ReturnFinally {
public static void main(String[] args) {
System.out.println(test11());
}
public static String test11() {
try {
System.out.println("try");
return test12();
} finally {
System.out.println("finally");
}
}
public static String test12() {
System.out.println("test12");
return "after return";
}
}
运行结果
try
test12
finally
after return
通过结果分析可以看出来,finally 都是在 return 之前运行的,那么有人该想了,如果在 finally 改变一下返回结果的值的值,那么最终的值会不会发生改变?
public class ReturnFinally {
public static void main(String[] args) {
System.out.println(test11());
}
public static int test11() {
int n=0;
try {
System.out.println("try");
n+=10;
return n;
} finally {
System.out.println("finally");
n+=20;
System.out.println("n="+n);
}
}
}
运行结果
try
finally
n=30
10
运行的顺序和之前都一样,但是结果可能出乎大家的意料。我来给大家分析一下:运行到 n+=10;的时候,n 的值为10,然年执行 return n;此时的 n 并没有发生改变,然后程序会走到 finally 语句块中,执行 n+=20; n 的值发生改变,在原来的基础之上加20,所以输出的结果是 n=30,但是要注意,Java 方法返回数据,都是以值的方式返回的,也就是在返回的时候 n 是多少就是多少,不会改变了。有两种种情况会覆盖返回的结果
public class ReturnFinally {
public static void main(String[] args) {
System.out.println(test11());
}
public static String test11() {
String s = new String();
try {
System.out.println("try");
s+="try";
return s;
} finally {
System.out.println("finally");
s+="finally";
System.out.println("s="+s);
return s;
}
}
}
运行结果
try
finally
s=tryfinally
tryfinally
从这例子中可以看出,在 finally 写上一个 return 的话,会覆盖掉之前返回的结果。
第二种:
public class ReturnFinally {
public static void main(String[] args) {
System.out.println(test11());
}
public static List test11() {
List s = new ArrayList();
try {
System.out.println("try");
s.add("try");
return s;
} finally {
System.out.println("finally");
s.add("finally");
System.out.println("s="+s);
return s;
}
}
}
运行结果
try
finally
s=[try, finally]
[try, finally]
看到结果有人就纳闷了,同样的写法,return n 的时候 n 也没有发生变化,但是这里的 List 怎么变了。这个涉及到一个知识点,就是传值还是传地址的问题。有兴趣大家可以查阅一下资料,简单的说就是上面的那个例子 return n 的时候实际上是有一个新的 n 进行返回了,返回的是 n 的值,不是它的地址;但是 List 这个例子,在 new ArrayList 的时候在堆内存中声明一块空间,return 返回的是 List 所对应的地址,所以在 finally 中进行修改,它会跟着变化。
总结
Java 中 finally 无论 try 与 catch 中遇到任何问题,finally 语句中的内容都会被执行,如果返回的值是对象,那么 finally 中做出的修改,最终结果会进行修改,如果是普通数据类型,就不会发生变化。