如何在Java中为错误案例实现'finally'

如何在Java中为错误案例实现'finally',java,exception-handling,Java,Exception Handling,如果发生任何错误,我需要一些代码来触发。基本上我需要一个finally块,它只在异常情况下执行。我会这样做: HttpURLConnection post(URL url, byte[] body) throws IOException { HttpURLConnection connection = url.openConnection(); try { OutputStream out = connection.getOutputStream();

如果发生任何错误,我需要一些代码来触发。基本上我需要一个
finally
块,它只在异常情况下执行。我会这样做:

HttpURLConnection post(URL url, byte[] body) throws IOException {
    HttpURLConnection connection = url.openConnection();
    try {
        OutputStream out = connection.getOutputStream();
        try {
            out.write(body);
        } finally {
            out.close();
        }
        return connection;
    } catch (Throwable t) {
        connection.disconnect();
        throw t;
    }
}
看起来不错,只是它无法编译:我的函数无法抛出
Throwable

我可以重新写:

    } catch (RuntimeException e) {
        connection.disconnect();
        throw e;
    } catch (IOException e) {
        connection.disconnect();
        throw e;
    }
但即使这样,我a)丢失了所有错误,b)每当我更改实现以抛出不同类型的异常时,都必须修复此代码


是否可以按常规方式处理此问题?

您可以使用finally块,并添加一个标志以指示成功

bool success = false;
try {
    //your code
    success = true;
    return retVal;
} finally {
    if (!success) {
        //clean up
    }
}

您可以使用finally块,并添加一个标志来指示成功

bool success = false;
try {
    //your code
    success = true;
    return retVal;
} finally {
    if (!success) {
        //clean up
    }
}

Throwable
有两个子类,
Error
Exception
。用于
错误
的Javadocs说:

错误是Throwable的一个子类 表示严重的问题 合理应用不应尝试 抓住。大多数这样的错误是错误的 异常情况。死亡 错误虽然是“正常”情况,但仍然存在 也是Error的一个子类,因为大多数 应用程序不应试图捕获 它

因此,除非这是一个真正不寻常的情况,否则您可以只关注
异常

catch (IOException e) {
    connection.disconnect();
    throw e;
}
catch (RuntimeException e) {
    connection.disconnect();
    throw e;
}
catch (Exception e) {
    connection.disconnect();
    throw new IOException(e);
}

Throwable
有两个子类,
Error
Exception
。用于
错误
的Javadocs说:

错误是Throwable的一个子类 表示严重的问题 合理应用不应尝试 抓住。大多数这样的错误是错误的 异常情况。死亡 错误虽然是“正常”情况,但仍然存在 也是Error的一个子类,因为大多数 应用程序不应试图捕获 它

因此,除非这是一个真正不寻常的情况,否则您可以只关注
异常

catch (IOException e) {
    connection.disconnect();
    throw e;
}
catch (RuntimeException e) {
    connection.disconnect();
    throw e;
}
catch (Exception e) {
    connection.disconnect();
    throw new IOException(e);
}

除非我弄错了,否则异常不需要一个
finally
块来停止执行并执行您需要的操作,比如清理或错误缓解

try {
  // Do some work! 
  // Fail
} catch (IOException e) {
  // Clean up, alert user, expected error
} catch (Exception e) {
  // Not so much expected, but lets try to handle this
}
错误应该来自您实现的类和方法,这些基本上是您的想法。考虑执行流程和错误的传播。如果上面的方法没有捕获特定的异常,那么无论调用什么,都会看到异常


Throwable只是一个具有子类的顶级类。例外通常是包罗万象的。请记住,您还可以实现自己的异常来处理任务

除非我弄错了,否则异常不需要一个
finally
块来停止执行并执行您需要的操作,比如清理或错误缓解

try {
  // Do some work! 
  // Fail
} catch (IOException e) {
  // Clean up, alert user, expected error
} catch (Exception e) {
  // Not so much expected, but lets try to handle this
}
错误应该来自您实现的类和方法,这些基本上是您的想法。考虑执行流程和错误的传播。如果上面的方法没有捕获特定的异常,那么无论调用什么,都会看到异常


Throwable只是一个具有子类的顶级类。例外通常是包罗万象的。请记住,您还可以实现自己的异常来处理任务

检查过的异常不是很奇妙吗?@cdhowie:我也不喜欢检查过的异常,但这确实是一个错误的案例,可以扔掉被检查但不被检查;运行时中没有声明“throws-XxxError”,但是如果您试图(重新)突然抛出XxxError,它将被选中-嗯??怎么回事?Checked exception异常应该使用Throwable的CheckedException抽象子类完成,该子类由编译器检查,而不是当前的“魔法”——当然,这使我能够将Checked exception异常作为Throwable进行重试,但我不确定这是否是件坏事。@softwaremonkey:实际上
错误
没有被检查,我只是检查了一下。:)您完全可以捕获并重新抛出
Error
,而不必在
throws
子句中提及它。不过,这会给我的解决方案增加另一个案例,使其更不易维护。事实上,Java没有使用
CheckedException
Java,而是使用了两个未经检查的树,
RuntimeException
Error
,并检查其他所有内容;然而,抛弃品本身仍然是破碎的。(我从来没有试图捕捉并重新抛出一个错误,这是很明智的)。被检查的异常难道不是很奇妙吗?@cdhowie:我也不喜欢被检查的异常,但这确实是一个错误和可丢弃的被检查但不被检查的情况;运行时中没有声明“throws-XxxError”,但是如果您试图(重新)突然抛出XxxError,它将被选中-嗯??怎么回事?Checked exception异常应该使用Throwable的CheckedException抽象子类完成,该子类由编译器检查,而不是当前的“魔法”——当然,这使我能够将Checked exception异常作为Throwable进行重试,但我不确定这是否是件坏事。@softwaremonkey:实际上
错误
没有被检查,我只是检查了一下。:)您完全可以捕获并重新抛出
Error
,而不必在
throws
子句中提及它。不过,这会给我的解决方案增加另一个案例,使其更不易维护。事实上,Java没有使用
CheckedException
Java,而是使用了两个未经检查的树,
RuntimeException
Error
,并检查其他所有内容;然而,抛弃品本身仍然是破碎的。(我从来没有尝试捕捉并重新抛出错误,这是非常明智的)。更新为只抛出IOException。在我看来,用IOException包装所有内容不是一个好主意。任何排列的边界都将以这种方式结束。没错,错误比异常更为异常,但是
finally
块在不更改异常类型的情况下透明地处理所有内容。我希望尽可能地复制这种行为。@SnakE-finally
技术不需要包装,因为它不允许IOException(和RuntimeException,但Runti)之外的任何其他异常类型