finally块总是在Java中执行吗?
考虑到这段代码,我是否可以绝对确保无论finally块总是在Java中执行吗?,java,error-handling,return,try-catch-finally,Java,Error Handling,Return,Try Catch Finally,考虑到这段代码,我是否可以绝对确保无论something()是什么,都始终执行finally块 try { something(); return success; } catch (Exception e) { return failure; } finally { System.out.println("I don't know if this will get printed out"); } 是,执行try或catch代
something()
是什么,都始终执行finally
块
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("I don't know if this will get printed out");
}
是,执行
try
或catch
代码块后,将调用finally
唯一不会调用finally
的时间是:
System.exit()
Runtime.getRuntime().halt(exitStatus)
try
或catch
块中的无限循环(或其他一些不可中断、不终止的语句)finally
块将由守护进程线程执行,并且在调用finally
之前退出所有其他非守护进程线程除非程序异常终止(如调用System.exit(0)),否则始终执行finally。因此,您的sysout将被打印出来是的,它将被调用。这就是使用finally关键字的全部意义。如果跳出try/catch块可以跳过finally块,那么这与将System.out.println放在try/catch之外是一样的。示例代码:
public static void main(String[] args) {
System.out.println(Test.test());
}
public static int test() {
try {
return 0;
}
finally {
System.out.println("finally trumps return.");
}
}
输出:
3
2
最终战胜了回归。
0
始终执行finally块,除非由于JVM崩溃或调用系统而导致程序异常终止。退出(0)
除此之外,从finally块中返回的任何值都将覆盖在执行finally块之前返回的值,因此在使用try finally时要小心检查所有退出点。此外,尽管这是一种不好的做法,但如果finally块中有return语句,它将胜过常规街区的任何其他回报。也就是说,以下块将返回false:
try { return true; } finally { return false; }
从finally块抛出异常也是如此。返回finally将抛出任何异常 思考这个问题的逻辑方法是:
除了最后替换try块中的return中关于return的一点之外,异常也是如此。抛出异常的finally块将替换try块中抛出的返回或异常。我尝试了上面的示例,但做了一些修改-
public static void main(final String[] args) {
System.out.println(test());
}
public static int test() {
int i = 0;
try {
i = 2;
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
}
}
上述代码输出:
最后,王牌回归。二, 这是因为当
返回i时执行代码>时i
的值为2。在此之后,执行finally
块,其中12被分配给i
,然后执行System.out
out
class A {
public static void main(String args[]){
DataInputStream cin = new DataInputStream(System.in);
try{
int i=Integer.parseInt(cin.readLine());
}catch(ArithmeticException e){
}catch(Exception e){
System.exit(0);//Program terminates before executing finally block
}finally{
System.out.println("Won't be executed");
System.out.println("No error");
}
}
}
try {
CODE inside the try block
}
finally {
FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).
执行finally
块后,try
块返回2,而不是返回12,因为此返回语句不会再次执行
如果您将在Eclipse中调试此代码,那么您会感觉在执行System.out
offinally
阻塞return
语句之后,会再次执行try
阻塞。但事实并非如此。它只是返回值2。最终总是运行,这就是关键所在,只是因为它在返回后出现在代码中并不意味着它就是这样实现的。Java运行时有责任在退出try
块时运行此代码
例如,如果您具有以下内容:
int foo() {
try {
return 42;
}
finally {
System.out.println("done");
}
}
运行时将生成如下内容:
int foo() {
int ret = 42;
System.out.println("done");
return 42;
}
如果抛出未捕获的异常,则finally
块将运行,异常将继续传播 因为除非调用System.exit()
(或线程崩溃),否则将始终调用finally块。这就是finally块的全部思想。它让你确保你做了清理,否则可能会被跳过,因为你返回,当然还有其他事情
最终被调用,无论try块中发生了什么(除非调用System.exit(int)
或Java虚拟机出于其他原因退出)。除了其他响应,必须指出,“finally”有权覆盖try..catch块的任何异常/返回值。例如,以下代码返回12:
public static int getMonthsInYear() {
try {
return 10;
}
finally {
return 12;
}
}
类似地,以下方法不会引发异常:
public static int getMonthsInYear() {
try {
throw new RuntimeException();
}
finally {
return 12;
}
}
而以下方法确实会抛出它:
public static int getMonthsInYear() {
try {
return 12;
}
finally {
throw new RuntimeException();
}
}
这是因为您将i的值指定为12,但没有将i的值返回给函数。正确的代码如下:
public static int test() {
int i = 0;
try {
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
return i;
}
}
下面是Java语言规范中的官方词汇
首先执行try
块,执行带有finally
块的try
语句。还有一个选择:
try{
int divideByZeroException = 5 / 0;
} catch (Exception e){
System.out.println("catch");
return; // also tried with break; in switch-case, got same output
} finally {
System.out.println("finally");
}
catch
finally
- 如果
try
块的执行正常完成,[…]
- 如果
try
块的执行由于值V的抛出而突然完成,[…]
- 如果执行
try
块由于任何其他原因突然完成,则执行finally
块。还有一个选择:
- 如果finally块完成n
public static void main(String args[]) throws Exception {
Object obj = new Object();
try {
synchronized (obj) {
obj.wait();
System.out.println("after wait()");
}
} catch (Exception ignored) {
} finally {
System.out.println("finally");
}
}
// import java.util.concurrent.Semaphore;
public static void main(String[] args) {
try {
// Thread.sleep(Long.MAX_VALUE);
// Thread.currentThread().join();
// new Semaphore(0).acquire();
// while (true){}
System.out.println("after sleep join semaphore exit infinite while loop");
} catch (Exception ignored) {
} finally {
System.out.println("finally");
}
}
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public static void main(String args[]) {
try {
unsafeMethod();
//Runtime.getRuntime().halt(123);
System.out.println("After Jvm Crash!");
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
unsafe.putAddress(0, 0);
}
public static void main(String args[]) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
printThreads("Daemon Thread printing");
// just to ensure this thread will live longer than main thread
Thread.sleep(10000);
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
};
Thread daemonThread = new Thread(runnable);
daemonThread.setDaemon(Boolean.TRUE);
daemonThread.setName("My Daemon Thread");
daemonThread.start();
printThreads("main Thread Printing");
}
private static synchronized void printThreads(String str) {
System.out.println(str);
int threadCount = 0;
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread t : threadSet) {
if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
System.out.println("Thread :" + t + ":" + "state:" + t.getState());
++threadCount;
}
}
System.out.println("Thread count started by Main thread:" + threadCount);
System.out.println("-------------------------------------------------");
}
main Thread Printing
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED
Thread :Thread[main,5,main]:state:RUNNABLE
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE
Thread count started by Main thread:3
-------------------------------------------------
Daemon Thread printing
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE
Thread count started by Main thread:2
-------------------------------------------------
Process finished with exit code 0
try{
int divideByZeroException = 5 / 0;
} catch (Exception e){
System.out.println("catch");
return; // also tried with break; in switch-case, got same output
} finally {
System.out.println("finally");
}
catch
finally
public static void main(String[] args) {
System.out.println(test().toString());
}
public static StringBuffer test() {
StringBuffer s = new StringBuffer();
try {
s.append("sb");
return s;
} finally {
s.append("updated ");
}
}
sbupdated
public class SomeTest {
private static StringBuilder sb = new StringBuilder();
public static void main(String args[]) {
System.out.println(someString());
System.out.println("---AGAIN---");
System.out.println(someString());
System.out.println("---PRINT THE RESULT---");
System.out.println(sb.toString());
}
private static String someString() {
try {
sb.append("-abc-");
return sb.toString();
} finally {
sb.append("xyz");
}
}
}
-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz
private static String someString() {
StringBuilder sb = new StringBuilder();
try {
sb.append("abc");
return sb.toString();
} finally {
sb = null; // Just an example, but you can close streams or DB connections this way.
}
}
System.out.println(foo());
....
int foo(){
int x = 2;
try{
return x++;
} finally{
System.out.println(x);
}
}
3
2