128

我正在审查一些新代码。该程序只有一个 try 和一个 finally 块。由于排除了 catch 块,如果 try 块遇到异常或任何可抛出的东西,它是如何工作的?它只是直接进入finally块吗?

4

11 回答 11

135

如果 try 块中的任何代码可以抛出已检查异常,则它必须出现在方法签名的 throws 子句中。如果抛出未经检查的异常,它就会从方法中冒出来。

finally 块总是被执行,无论是否抛出异常。

于 2010-12-30T02:54:07.830 回答
95

关于try/的一个小提示finally:finally 将始终执行,除非

  • System.exit()叫做。
  • JVM 崩溃。
  • 块永远不会结束(try{}例如无限循环)。
于 2010-12-30T09:48:47.157 回答
39

Java 语言规范(1)描述了如何try-catch-finally执行。没有捕获相当于没有捕获能够捕获给定的 Throwable。

  • 如果 try 块的执行由于抛出值 V 而突然完成,那么有一个选择:
    • 如果 V 的运行时类型可分配给 try 语句的任何 catch 子句的参数,则 ...<br> ...
    • 如果 V 的运行时类型不可分配给 try 语句的任何 catch 子句的参数,则执行 finally 块。然后有一个选择:
      • 如果 finally 块正常完成,那么 try 语句会因为抛出值 V 而突然完成。
      • 如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S 突然完成(并且值 V 的抛出被丢弃并被遗忘)。

(1) try-catch-finally的执行

于 2010-12-30T10:28:44.360 回答
17

内部 finally 在将异常抛出到外部块之前执行。

public class TryCatchFinally {

  public static void main(String[] args) throws Exception {

    try{
        System.out.println('A');
        try{
            System.out.println('B');
            throw new Exception("threw exception in B");
        }
        finally
        {
            System.out.println('X');
        }
        //any code here in the first try block 
        //is unreachable if an exception occurs in the second try block
    }
    catch(Exception e)
    {
        System.out.println('Y');
    }
    finally
    {
        System.out.println('Z');
    }
  }
}

结果是

A
B
X
Y
Z
于 2016-07-01T15:00:11.577 回答
6

finally 块总是在 try 块结束后运行,无论 try 正常结束还是由于异常而异常结束,呃,throwable。

如果 try 块中的任何代码抛出异常,则当前方法只是重新抛出(或继续抛出)相同的异常(在运行 finally 块之后)。

如果 finally 块抛出异常 / 错误 / throwable,并且已经有一个待处理的 throwable,它会变得很丑。坦率地说,我完全忘记了发生了什么(对于我多年前的认证而言)。我认为这两个 throwable 都连接在一起,但是您必须做一些特殊的巫术(即 - 我必须查找的方法调用)才能在“最终”被吐出之前解决原始问题,呃,吐出。

顺便说一句,try/finally 对于资源管理来说是一件很常见的事情,因为 java 没有析构函数。

例如 -

r = new LeakyThing();
try { useResource( r); }
finally { r.release(); }  // close, destroy, etc

“最后”,还有一个提示:如果您确实费心放入一个 catch,要么捕获特定的(预期的)可抛出的子类,要么只捕获“Throwable”,而不是“Exception”,以获得一般的捕获所有错误陷阱。太多的问题,例如反射错误,抛出“错误”,而不是“异常”,并且这些问题将被任何“捕获所有”编码为:

catch ( Exception e) ...  // doesn't really catch *all*, eh?

改为这样做:

catch ( Throwable t) ...
于 2010-12-30T03:25:45.113 回答
4

版本 7 之前的 Java 版本允许try-catch-finally的这三种组合......

try - catch
try - catch - finally
try - finally

finally无论tryor/andcatch块中发生了什么,块都将始终执行。所以如果没有catch阻塞,这里就不会处理异常。

但是,您仍然需要在代码中的某处使用异常处理程序——当然,除非您希望您的应用程序完全崩溃。这取决于您的应用程序的体系结构,该处理程序的确切位置。

  • Java try 块必须后跟 catch 或 finally 块。
  • 对于每个 try 块,可以有零个或多个 catch 块,但只有一个 finally 块。
  • 如果程序退出(通过调用 System.exit() 或通过导致导致进程中止的致命错误),将不会执行 finally 块。
于 2016-10-16T17:15:23.720 回答
2

如果遇到异常或任何可抛出的东西,try 块如何工作

异常被抛出块外,就像在任何其他没有被捕获的情况下一样。

无论 try 块如何退出,都将执行 finally 块——无论是否有任何捕获,无论是否有匹配的捕获。

catch 块和 finally 块是 try 块的正交部分。你可以有一个或两个。使用 Java 7,您将无法拥有这两者!

于 2010-12-30T03:24:49.343 回答
1

你不试试那个程序吗?它将转到 finally 块并执行 finally 块,但是不会处理异常。但是,该异常可以在 finally 块中被否决!

于 2010-12-30T02:55:25.270 回答
1

finally 块在 try 块完成后执行。如果在 try 块离开时抛出了某些东西,则执行 finally 块。

于 2010-12-30T03:38:09.793 回答
0

try块内部,我们编写可以引发异常的代码。该catch块是我们处理异常的地方。finally无论是否发生异常,该块总是被执行。

现在如果我们有 try-finally 块而不是 try-catch-finally 块,那么异常将不会被处理,并且在 try 块而不是控制去 catch 块之后它将进入 finally 块。当我们不想对异常做任何事情时,我们可以使用 try-finally 块。

于 2019-09-15T09:50:08.317 回答
0

无论是否在try块中抛出异常 -finally都会执行块。异常不会被捕获。

于 2020-07-03T11:08:28.133 回答