Java 如何使用vavr仅记录特定异常

Java 如何使用vavr仅记录特定异常,java,functional-programming,vavr,Java,Functional Programming,Vavr,因此,我有一个方法返回VavrTry: public Try request(){…} 请求来自我无法修改的源。目前,我对请求的结果进行平面映射,并根据结果是否有错误,返回尝试,结果中的数据异常或成功: public Try fetchData(){ 返回请求().flatMap(结果->{ if(result.hasError()){ 返回Try.failure(新的FailedRequestException()); }否则{ 返回Try.success(result.data()); }

因此,我有一个方法返回Vavr
Try

public Try request(){…}
请求
来自我无法修改的源。目前,我对
请求
的结果进行平面映射,并根据
结果
是否有错误,返回
尝试
,结果中的数据异常或成功:

public Try fetchData(){
返回请求().flatMap(结果->{
if(result.hasError()){
返回Try.failure(新的FailedRequestException());
}否则{
返回Try.success(result.data());
}
});
}
我想要的是在一些使用
fetchData
的地方,如果
Try
成功,则首先对数据执行一些操作;如果失败,则记录错误(如果错误是
FailedRequestException
),否则,对异常执行其他操作,如下所示:

fetchData()。然后(data->…).onFailure(ex->{
如果(例如FailedRequestException){
log.error(“无法获取数据:+ex.getMessage());
}否则{
//做一些例外的事情
...
}
});

这种方法的问题是
fetchData
返回一个
Try
,因此调用者无法知道
FailedRequestException
是可能失败的一部分。我可以让
fetchData
返回
Try
,但这感觉也不对。有没有什么方法可以更优雅地完成上述任务?我也尝试过使用
匹配
案例
,但是
案例
需要一个
函数
作为处理程序,而不是
消费者
来总结:您实际上有3种场景(成功、失败与FailedRequestException一起失败、任何其他失败)。这听起来像是一个模式匹配的工作!让我们使代码与业务需求一样可见和表达:)

FWIW,您可以将
fetchData
实现重写为:

Try(request())
    .mapFailure(Case($(), ignored -> new FailedRequestException()))
    .map(Result::data);
根据经验,当上下文(成功或失败)可能发生变化时,请尝试坚持使用
flatMap
。在当前的
fetchData
实现中,成功仍然是成功,失败仍然是失败,因此它是输入和输出之间的映射,因此使用
map
函数系列


干杯

谢谢你的回复。如果我执行建议的
匹配
,则类型将被删除,如果成功,函数需要一个
对象
(您给出的示例中的
数据
)。另外,不同的
案例
需要一个
函数
供应商
或一个简单的返回值,我想使用
消费者
。不,类型不会被删除,但在您正确编写代码之前,编译器错误会误导您,因为JDK推理处理不当。至于使用消费者,这没有意义,在函数式编程中,总是返回一个值。消费者不返回任何内容(无效)。函数的返回类型是什么?如果它也返回void,那么请参见Vavr文档:部分“执行副作用”是,然后
run
执行了该技巧,尽管现在代码感觉不再正确。也许我会去看看是否可以重构代码,使其不需要使用者。如果vavr有一个编剧monad那就太好了。编剧monad在这件事上不会有太大变化。即使使用Writer monad(例如在Haskell中),函数也必须返回一个值,并且所有分支都必须返回相同类型的值。我认为主要的问题是Java原语
void
和类
void
是不同的。许多函数返回原语,这会阻止在Vavr中返回值。如果您的函数返回
Void
,它将像Vavr的符咒一样工作,无需
run
needed;)您可以轻松地在记录器周围编写包装器,以返回Void!
Try(request())
    .mapFailure(Case($(), ignored -> new FailedRequestException()))
    .map(Result::data);