使用 Lambda 包装具有相同异常处理的方法

pus*_*eal 1 java lambda

我有很多方法想用相同的 try/catch 处理来包装。我认为 lambdas 可以在这里帮助我,但我很难弄清楚语法。

这是我要实现的目标的背景。

method1(..., result -> method2(result, ...));
Run Code Online (Sandbox Code Playgroud)

方法 2 是方法 1 结果的处理程序。我想用一个通用的 try/catch 语句包装 method2,该语句对大量处理程序来说是通用的,而不必将该语句复制/粘贴到所有处理程序。

注意:这些是未经检查的异常。

*edit - 我正在尝试做的具体例子。

我正在使用 Vert.x,他们使用通用的 Handlers 设计模式。这是他们的 SQL 接口的示例

query(String sql, Handler<AsyncResult<ResultSet>> resultHandler)
Run Code Online (Sandbox Code Playgroud)

Handler是一个简单的1个函数接口:

void handle(E event)
Run Code Online (Sandbox Code Playgroud)

所以基本上,执行“sql”中定义的查询,并将结果发送到resultHandler。下面是一个使用中的例子:

connection.query("SELECT * from table1", asyncResult -> {
    // do something with results
}
Run Code Online (Sandbox Code Playgroud)

以上使用了他们文档的标准编码风格。由于各种原因,我个人更喜欢在命名函数中处理结果,因此它更改为:

connection.query("SELECT * from table1", asyncResult -> method1(asyncResult));

void method1(AsyncResult<ResultSet> asyncResult) {
    // do something with results
}
Run Code Online (Sandbox Code Playgroud)

我无法控制 query() 接口,所以我坚持使用这种模式。我不确定 Tagir 的解决方案是否适用于这种情况,但我会在早上尝试一下。

*edit2 - 我应该注意到我试图将上面示例中的 method1 包装在异常包装器中,所以理想情况下,我会在 query() 调用中添加包装器调用。所以我正在寻找的是这样的:

connection.query("SELECT * from table1", wrap(asyncResult -> method1(asyncResult)));
Run Code Online (Sandbox Code Playgroud)

显然,我不能那样使用它,因为它会将原始 lambda 作为参数进行评估,但从概念上讲,这就是我想要添加包装的地方。

Tag*_*eev 6

您可以使用Runnable函数式接口来实现处理异常的方法:

public static void handleExceptions(Runnable r) {
    try {
        r.run();
    }
    catch(RuntimeException ex) {
        ex.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

并这样称呼它:

handleExceptions(() -> method2(foo, bar));
Run Code Online (Sandbox Code Playgroud)

如果您method2产生了结果,您应该确定发生异常时的默认结果(并且您不在处理程序中重新抛出它)。您可以在Supplier这种情况下使用功能接口:

public static <T> T handleExceptions(Supplier<T> r, T defaultValue) {
    try {
        return r.get();
    }
    catch(RuntimeException ex) {
        ex.printStackTrace();
        return defaultValue;
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样调用:

// set result to null if exception occurred
result = handleExceptions(() -> method2(foo, bar), null);
Run Code Online (Sandbox Code Playgroud)

或者

// do not modify the result if exception occurred
result = handleExceptions(() -> method2(foo, bar), result);
Run Code Online (Sandbox Code Playgroud)