Java try catch 最后似乎毫无意义

Java try catch finally seems pointless

这是一个很愚蠢的问题,但我不明白 catch 和 finally 的结合使用。据我所知,无论是否会引发异常,都会执行 catch 块之后的代码,所以为什么要使用

try
{
    doSomething();
}
catch(Exception e)
{
    e.printStackTrace();
}
finally
{
    doSomethingInFinally();
}

而不是

try
{
    doSomething();
}
catch(Exception e)
{
    e.printStackTrace();
}

doSomethingInFinally();

?我总是看到人们使用第一种模式,但我认为这是额外的代码。

因为您将在 try {} 语句中途停止执行。在您的 finally 中,您可能担心关闭文件句柄、套接字等

我们几乎从不捕捉(或应该捕捉)Exception。我们将捕获 Exception 的子类。在那种情况下,如果 doSomething() 抛出 catch 子句未处理的异常,则 doSomethingInFinally() 将不会在第二个示例中执行。

有些情况下您的建议不起作用

  • 根本没有catch语句(抛出异常时方法不会继续执行)

  • catch块重新抛出异常

  • try 块中有 return 语句。
  • catch 语句不处理超类型异常(如您的情况下的 Throwable)。

我能给你的最好解释是将你引导至 java doc

来自 Java 文档:

This ensures that the finally block is executed even if an unexpected exception occurs.

还有一个跟进

Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

这是一个简单的场景,为什么 finally 很重要:

LeakableIO i;
try{
  i = new LeakableIO();
  // do more
}catch(MyException e){
   return null;
}

i.close()

我们假设有一个错误所以return被执行了,你认为i.close()会不会在return之后被调用?答案是否定的。

不同之处在于,一种形式可能会错过最后的内容。

doSomethingAfter 几乎总是 被调用。唯一不会被调用的情况是 doSomethingWithException 抛出异常。

public void test1() {
    try {
        doSomething();
    } catch (Exception e) {
        doSomethingWithException();
    }

    doSomethingAfter();
}

doSomethingAfter总是 被调用,无论发生什么。

public void test2() {
    try {
        doSomething();
    } catch (Exception e) {
        doSomethingWithException();
    } finally {
        doSomethingAfter();
    }
}

一个return也挡不住。同样 doSomethingAfter 总是 被调用。

public void test3() {
    try {
        doSomething();
    } catch (Exception e) {
        doSomethingWithException();
        return;
    } finally {
        doSomethingAfter();
    }
}
public int method1()
{
    try
    {
       return 1;
        doSomething();
    }
    catch(Exception e)
    {
       return 0;
        e.printStackTrace();
    }
    finally
    {
       System.out.println("Hello user");
    }
}

在上述方法中,Hello user 将始终被打印出来。因为存在于 finally 块中的代码将始终执行。 基本上在 JDBC 中,finally 块用于关闭连接。