在Java 8中使用Function抽象try / catch

时间:2015-12-25 11:58:13

标签: java eclipse functional-programming java-8

我最近发现自己编写了以下形式的许多块:

try {
    return Optional.of(thing.doSomething(arg));
} catch (Exception e) {
    System.out.println(e.getMessage());
    return Optional.empty();
}

这是必要的,因为某些方法表明它们可能会抛出异常,如果我不使用try / catch块包围这些方法,Eclipse会对我大吼。

所以我写了这个:

public static <A, T> Optional<T> tryOpt (Function<A, T> f, A arg) {
    try {
        return Optional.of(f.apply(arg));
    } catch (Exception e) {
        System.out.println(e.getMessage());
        return Optional.empty();
    }
}

因此,传递给tryOpt的任何函数都包含在try / catch块中并安全执行,其结果作为Optional返回。但是Eclipse仍然因使用它而大喊大叫:

return tryOpt(
          ((x) -> thing.doSomething(x)),
          arg);

我的问题是,有没有办法让我告诉Eclipse和/或java编译器它没关系,并且我在try /中间接包含有问题的方法抓住了?或者我只是误解了一些关于java如何工作的东西,在这种情况下,有人会介意启发我吗?或者,另一方面,在这种情况下,我可以安全地忽略Eclipse的红线警告吗?

3 个答案:

答案 0 :(得分:4)

Function.apply不允许抛出异常,因此编译器在传入执行该操作的lambda表达式时会抱怨。

您可以使用允许抛出异常的功能接口来解决此问题。 (也许这样的接口已经存在于java.util。*包之一中):

public static <A, T> Optional<T> tryOpt (Fn<A, T> f, A arg) {
    try {
        return Optional.of(f.apply(arg));
    } catch (Exception e) {
        System.out.println(e.getMessage());
        return Optional.empty();
    }
}


public static interface Fn<A, T> {
      T apply(A a) throws Exception;
}

答案 1 :(得分:2)

如果它是红线,则不是警告,但这是一个错误。

在这种情况下,Function<A,R>接口声明了一个抛出异常的方法,但是你的实现确实如此。在这种情况下,最好的办法是创建自己的函数接口,声明一个抛出异常的方法,例如

public interface SupplierWithException<R> {R get();}

你这样使用它:

return asOptional(() -> thing.doSomething(arg1, arg2, arg3));

但是,我建议只是吞咽异常是不好的形式;如果你使用asOptional方法很多,这表明你的代码部分(你使用的库?)之间的阻抗不匹配。您可以将异常重新抛出为RuntimeException,也可以使用显式处理异常的RxJava。

答案 2 :(得分:1)

主要问题是lambdas如何与检查异常混淆,设计以这种方式进行,这可能导致尴尬的解决方案,例如将每个调用包装到抛出使用它们的每个lambda内的方法。

我最终使用了一个包装器来管理这个,比如:

  @FunctionalInterface
  public interface FunctionThrowing<T, R>
  {
    R apply(T t) throws Exception;
  }


  public static <T, R> Function<T, R> wrapFunction(FunctionThrowing<T, R> function)
  {
    return a -> {
      try
      {
        return function.apply(a);
      } catch (Exception exception)
      {
        throw exception;
        return null;
      }
    };
  }

这基本上包含了一个函数,它返回一个处理已检查异常的函数并将其转换为未经检查的异常,这样你就不需要用try/catch块来包装每个调用,但你仍然没有&# 39;失去捕捉异常的能力(因为它变得不受控制)。