我想在catch和final块中运行两个不同的方法。我已经找到了AutoCloseable接口,但是我只需要在异常情况下触发一些东西。
比如:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}有什么办法让它更简单吗?正如我说的,我熟悉AutoCloseable,但它只帮助我最终阻止。我还是不能在渔获物里面用它。
发布于 2020-02-14 11:02:32
您可以定义自己的接口,然后使用一些static runner方法:
public interface ErrorHandlingCloseable extends AutoCloseable {
void run() throws Exception;
void onError(Exception e);
static void execute(ErrorHandlingClosable ehc) throws Exception {
try(ErrorHandlingClosable temp = ehc) {
ehc.run();
} catch(Exception e) {
ehc.onError(e);
throw e;
}
}
}然后你就可以这样称呼它:
SomeService service = CreateService().andOpenTransaction();
ErrorHandlingCloseable.execute(new ErrorHandlingCloseable() {
public void run() throws Exception { service.doSomeMessyThingsInsideDB(); }
public void onError(Exception e) { service.rollbackTransaction(); }
public void close() throws Exception { service.closeConnection(); }
});但你看,还是很乱。
您甚至可以在您的interface中实现这个SomeService,但是这样就限制了run()方法总是调用doSomeMessyThingsInsideDB()。
另一种方法(但仍然类似)是使用Java8并创建一个助手函数interface。
public interface ThrowingRunnable {
void run() throws Exception;
}然后在某个地方使用static方法:
public static void execute(ThrowingRunnable action,
ThrowingRunnable onCatch,
ThrowingRunnable onFinally) throws Exception {
try(AutoCloseable ao = onFinally) {
action.run();
} catch(Exception e) {
onCatch.run();
throw e;
}
}有趣的部分可能是:try(AutoCloseable ao = onFinally),它“注册”要在到达finally时调用的onFinally方法。
这样就可以这样称呼它:
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);发布于 2020-02-14 10:57:06
你说你熟悉AutoCloseable,但你不使用它。您考虑过使用try-with-resources语句吗?
您的代码可以简化为:
try (SomeService service = CreateService().andOpenTransaction()) {
service.doSomeMessyThingsInsideDB();
} catch(exception e){
service.rollbackTransaction();
throw e;
}甲骨文在这方面有很好的文档,包括例子。
Note:具有资源的语句可以有catch并最终阻塞,就像普通try语句一样。在“使用资源的尝试”语句中,在声明的资源被关闭后,将运行任何catch或最终块。
回答您的问题,这是它所能得到的最简单的。如果您的类没有实现Closeable,那么您可以实现它或使用finally。
发布于 2020-02-14 11:28:06
第一步:处理异常
显然,您希望在关闭之前处理异常。然后,您需要在一个使用资源进行尝试的内部处理异常。
/** throws RuntimeException */
void process(Callable<Void> work, Consumer<Exception> onFail) {
try {
work.call();
} catch (Exception e) {
onFail(e);
}
}
try (SomeService service = CreateService().andOpenTransaction()) {
process(() -> service.doSomeMessyThingsInsideDB(),
e -> {
service.rollbackTransaction();
throw new IllegalStateException(e);
});
}这不是很令人满意,但同样也集成了AutoCloseable,可能会给出太少的用例。
第二步:使用AutoCloseable的
<SV extends AutoCloseable> void processAutoClosing(Supplier<SV> serviceFactory,
Callable<Void> work, Consumer<Exception> onFail) {
try (SV service = serviceFactory.get()) {
process(work, onFail);
}
}
processAutoClosing(...);https://stackoverflow.com/questions/60224866
复制相似问题