考虑到这段代码,我能绝对确定finally块总是执行的吗,不管something()是什么?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

当前回答

除非由于JVM崩溃或调用System.exit(0)而导致程序异常终止,否则finally块将始终执行。

除此之外,finally块中返回的任何值都将覆盖finally块执行之前返回的值,因此在使用try finally时,请注意检查所有退出点。

其他回答

是的,总是执行finally块。大多数开发人员使用此块来关闭数据库连接、resultset对象、语句对象,还使用到java休眠来回滚事务。

最后总是在结尾处调用

当您尝试时,它会执行一些代码,如果在尝试中发生了什么,那么catch将捕获该异常,您可以打印一些mssg或抛出错误,然后最后执行块。

Finally通常在执行清理时使用,例如,如果使用java中的扫描仪,则可能应该关闭扫描仪,因为它会导致其他问题,例如无法打开某些文件

除其他响应外,重要的是要指出,“finally”有权通过try重写任何异常/返回值。。捕捉块。例如,以下代码返回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();
    }
}

不,并非总是有一种例外情况//System.exit(0);在finally块阻止finally被执行之前。

  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");
        }
    }
}

公认的答案在几乎所有方面都是正确的,但它仍然只是事实的一半(好吧,95%的事实)。

假设以下代码:

private final Lock m_Lock = new ReentrantLock();
…
public final SomeObject doSomething( final SomeObject arg )
{
  final SomeObject retValue;
  try
  {
    lock.lock();
    retValue = SomeObject( arg );
  }
  finally
  {
    out.println( "Entering finally block");
    callingAnotherMethod( arg, retValue );
    lock.unlock();
  }
  
  return retValue;
}
…
try
{
   final var result = doSomething( new SomeObject() );
}
catch( final StackOverflowError e ) { /* Deliberately ignored */ }

调用doSomething()方法将几乎立即导致StackOverflowError。

锁也不会松开!

但是,当finally块总是被执行时(接受的答案中已经列出了例外情况),这怎么会发生呢?

这是因为不能保证finally块中的所有语句都真正执行!

如果在调用lock.unlock()之前调用System.exit()或throws语句,这将是显而易见的。

但示例代码中没有类似的内容…

除此之外,调用lock.unlock()之前finally块中的另外两个方法调用将导致另一个StackOverflowError…

瞧,锁没有松开!

虽然这样的示例代码很愚蠢,但在许多类型的软件中都可以找到类似的模式。只要最后一个街区没有发生什么丑恶的事情,一切都会好起来的…

有趣的事实是,它在Java的更高版本中不起作用(这意味着在更高的版本中,锁被释放了…)。不知道何时以及为什么会发生变化。

但您仍然必须确保finally块始终正常终止,否则它是否始终被执行可能无关紧要…