抛出异常的Java 8 Lambda函数?

新手上路,请多包涵

我知道如何创建对具有 String 参数并返回 int 的方法的引用,它是:

 Function<String, Integer>

但是,如果函数抛出异常,这将不起作用,例如定义为:

 Integer myMethod(String s) throws IOException

我将如何定义这个参考?

原文由 Rocky Pulley 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 436
2 个回答

您需要执行以下操作之一。

  • 如果是您的代码,则定义您自己的功能接口来声明检查的异常:
   @FunctionalInterface
  public interface CheckedFunction<T, R> {
     R apply(T t) throws IOException;
  }

并使用它:

   void foo (CheckedFunction f) { ... }

  • 否则,将 Integer myMethod(String s) 包装在不声明检查异常的方法中:
   public Integer myWrappedMethod(String s) {
      try {
          return myMethod(s);
      }
      catch(IOException e) {
          throw new UncheckedIOException(e);
      }
  }

接着:

   Function<String, Integer> f = (String t) -> myWrappedMethod(t);

或者:

   Function<String, Integer> f =
      (String t) -> {
          try {
             return myMethod(t);
          }
          catch(IOException e) {
              throw new UncheckedIOException(e);
          }
      };

原文由 jason 发布,翻译遵循 CC BY-SA 4.0 许可协议

您实际上可以使用处理异常的新接口扩展 Consumer (和 Function 等)——使用Java 8的 默认方法

考虑这个接口(扩展 Consumer ):

 @FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

    @Override
    default void accept(final T elem) {
        try {
            acceptThrows(elem);
        } catch (final Exception e) {
            // Implement your own exception handling logic here..
            // For example:
            System.out.println("handling an exception...");
            // Or ...
            throw new RuntimeException(e);
        }
    }

    void acceptThrows(T elem) throws Exception;

}

然后,例如,如果您有一个列表:

 final List<String> list = Arrays.asList("A", "B", "C");

如果你想使用它(例如 forEach )和一些抛出异常的代码,你通常会设置一个 try/catch 块:

 final Consumer<String> consumer = aps -> {
    try {
        // maybe some other code here...
        throw new Exception("asdas");
    } catch (final Exception ex) {
        System.out.println("handling an exception...");
    }
};
list.forEach(consumer);

但是有了这个新接口,你可以用 lambda 表达式实例化它,编译器就不会报错了:

 final ThrowingConsumer<String> throwingConsumer = aps -> {
    // maybe some other code here...
    throw new Exception("asdas");
};
list.forEach(throwingConsumer);

或者甚至只是让它更简洁!:

 list.forEach((ThrowingConsumer<String>) aps -> {
    // maybe some other code here...
    throw new Exception("asda");
});

更新

看起来 Durian 中有一个非常好的实用程序库部分称为 Errors ,它可以更灵活地用于解决这个问题。例如,在我上面的实现中,我明确定义了错误处理策略( System.out...throw RuntimeException ),而 Durian 的错误允许您通过大型套件即时应用策略实用方法。感谢 分享,@NedTwigg!

示例用法:

 list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));

原文由 jlb 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题