我最近发现自己编写了以下形式的许多块:
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的红线警告吗?
答案 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;失去捕捉异常的能力(因为它变得不受控制)。