finally 代码块的执行情况

作者:DeppWang原文地址

finally 块用来执行即使有异常也能执行的代码,常用于出现异常时关闭流,或者释放锁。finally 总会执行。

关闭流的栗子:

      InputStream is = null;
try {
is = new FileInputStream("inputfile.txt");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

释放锁的栗子:

// java.util.concurrent.ArrayBlockingQueue.java
final ReentrantLock lock = this.lock;
lock.lock(); // Lock only for visibility, not mutual exclusion
try {
int i = 0;
try {
for (E e : c) {
checkNotNull(e);
items[i++] = e;
}
} catch (ArrayIndexOutOfBoundsException ex) {
throw new IllegalArgumentException();
}
count = i;
putIndex = (i == capacity) ? 0 : i;
} finally {
lock.unlock();
}

关于 finally,常有下面几个考察点:

一、try 里有 return,finally 怎么执行?

finally 块里的代码在 return 之前执行。

因为程序执行 return 就意味着结束对当前函数的调用并跳出这个函数体,因此任何语句要执行都只能在 return 前执行。

ps:其实 void 方法也有 return 语句,它是一个隐式的 return 语句,只是默认返回 void 而已。在 Java 中,所有的方法都需要 return 语句结束。

public class Test {
public static int testFinally() {
try {
System.out.println("execute try");
return 1;
} catch (Exception ex) {
return 2; // return 1; 将结束方法,catch 不执行
} finally {
System.out.println("execute finally");
}
}
public static void main(String[] args) {
int result = testFinally();
System.out.println(result);
}
}

运行结果:

execute try
execute finally
1

你可能会想:如果 finally 后面还有代码,代码是否会执行,什么时候执行?

如果真有代码,那编译时就会报错,因为 return 后不能有代码。

二、如果 try-catch-finally 中都有 return,如何执行?

如果 try-catch-finally 中都有 return,因为 finally 块里的代码是在 return 之前执行,那么 finally 块中的 return 将会先执行,try 和 catch 的 return 将不会生效。相当于覆盖了 try 和 catch 中的 return 语句,最终返回到调用者那里的是 finally 中 return 的值。

public class Test {
public static int testFinally() {
try {
return 1;
} catch (Exception ex) {
return 2;
} finally {
System.out.println("execute finally");
return 3;
}
}
public static void main(String[] args) {
int result = testFinally();
System.out.println(result);
}
}

运行结果:

execute finally
3

一般使用 return 时,要么在 try 和 catch 中都写 return,要么执行完 try-catch-finally 后写 return,一般不会在 finally 里面写 return。

三、在 finally 中,能修改 return 的返回结果么?

当 try/catch 中有 return 时,在 finally 块中改变基本类型的数据对返回值没有任何影响;而在 finally 中改变引用类型的数据会对返回结果有影响。

/**
* try/catch 中有 return, 在 finally{} 中改变基本数据类型、引用类型对运行结果的影响
*/
public class Test {
public static int testFinally1() {
int result1 = 1;
try {
return result1;
} catch (Exception ex) {
result1 = 2;
return result1;
} finally {
result1 = 3;
System.out.println("execute testFinally1");
}
}
public static StringBuffer testFinally2() {
StringBuffer result2 = new StringBuffer("hello");
try {
return result2;
} catch (Exception ex) {
return null;
} finally {
result2.append("world");
System.out.println("execute testFinally2");
}
}
public static void main(String[] args) {
int test1 = testFinally1();
System.out.println(test1);
StringBuffer test2 = testFinally2();
System.out.println(test2);
}
}

运行结果:

execute testFinally1
1
execute testFinally2
helloworld

程序在执行到 return 时会先将返回值存储在一个指定位置,其次去执行 finally 块,最会再 return。返回值在 return 时就确定了。

如果返回的是对象引用,对象引用不变,但可以通过引用修改对象,对象改变了。

四、什么时候 finally 不会执行?

Java 程序中的 finally 块并不一定会被执行。至少有两种情况 finally 语句是不会执行的。

(1) try 语句没有被执行到。

即没有进入 try 代码块,对应的 finally 自然不会执行。

比如,在 try 语句之前 return 就返回了,这样 finally 不会执行;或者在程序进入 try 之前就出现异常,会直接结束,也不会执行 finally 块。

(2) 在 try/catch 块中有 System.exit(0) 来退出 JVM。

System.exit(0) 是终止 JVM 的,会强制退出程序,finally{} 中的代码就不会被执行。

](https://www.cnblogs.com/fudashi/p/6498205.html)

评论默认使用 ,你也可以切换到 来留言。