问题描述
如果Exception
失败,我想抛出从Try.ofCallable()
扩展的异常。
我有一个类型的呼叫对象:
final Callable<MyResponse> decoratedCallable =
circuitBreakerService.getDecoratedMethod(
myArg1,() -> myFunction(myArg1,myArg2,myArg3)
);
我正在尝试这样的事情:
Try.ofCallable(decoratedCallable).onFailure(throwable -> {
if (throwable instanceof CallNotPermittedException) {
throw new MyRuntimeExceptionA("msg1",throwable);
} else {
throw new MyRuntimeExceptionB("msg2",throwable);
}
});
如果MyRuntimeExceptionA
和MyRuntimeExceptionB
都扩展了RuntimeException
,但如果扩展了{{1,则行不通(包裹以上两条语句的函数抛出正确的异常MyRuntimeExceptionA和MyRuntimeExceptionB)) }}。
如果它们扩展Exception
,则无法将它们从主函数中抛出。
IDE要求将它们包装在try / catch中,这是我不想要的。
解决方法
您有两个选择。当您尝试解开Try
时可以通过以下代码获取值来抛出:
Try.ofCallable(decoratedCallable)
.getOrElseThrow(throwable -> {
if (throwable instanceof CallNotPermittedException) {
return new MyExceptionA("msg1",throwable);
} else {
return new MyExceptionB("msg2",throwable);
}
})
或在将错误映射代码移出之前,使用类似的代码进行>
Try.ofCallable(decoratedCallable)
.mapFailure(
Case(
$(instanceOf(CallNotPermittedException.class)),throwable -> new MyExceptionA("msg1",throwable)
),Case($(),throwable -> new MyExceptionB("msg2",throwable))
)
.get()
这两种解决方案仅在展开时抛出,因此,如果您想提早抛出,则必须提早解开。
否则,如果您使用的是Try
,我将采纳其他发表在评论中的建议,不要抛出异常。使用Try
的重点是要使用全部函数,而不要使用可能引发异常的部分函数。
我对vavr不太了解,但是在库的javadoc中查找时,您会看到onFailure方法需要使用Consumer 作为参数。问题在于,使用者不会声明检查异常,因此您将永远无法从lambda抛出检查异常。
话虽如此,我通常在这些情况下要做的是创建一个“包装”类,该类将接受检查的异常,该包装类所要做的就是捕获所有检查的异常并将它们包装在运行时异常中。例如:
public class ThrowingConsumerHelper {
public static <T> Consumer<T> throwingConsumer(
ThrowingConsumer<T> consumer) {
return object -> {
try {
consumer.accept(object);
} catch (Throwable t) {
throw new RuntimeException(t);
}
};
}
@FunctionalInterface
public interface ThrowingConsumer<T> {
void accept(T t) throws Exception;
}
}
然后像这样使用它:
import static ThrowingConsumerHelper.throwingConsumer;
public static void main(String[] args) {
onFailure(throwingConsumer(object -> { throw new Exception("Bug"); }));
}
public static void onFailure(Consumer<? super Throwable> consumer) {
// Do something
}