说我有这个方法:
public CompletionStage<SomeClass> getData() {
CompletableFuture<SomeClass> future = new CompletableFuture<>();
return CompletableFuture.runAsync(() -> {
// Fetch data from some source
// Then either
// future.complete(data);
// or fail
// future.completeExceptionally(e);
});
return future;
}
现在我想要一个方法,调用getData
,进行操作,然后返回CompletionStage<Either<ErrorResponse, Data>>
public CompletionStage<Either<ErrorResponse, Data>> modifyData() {
return getData()
.thenCompose(d -> CompletableFuture.completedFuture(Either.right(d)))
.exceptionally(e -> Either.left(ErrorResponse.create(e)));
}
当我这样做时,exceptionally
内的类型丢失,编译器认为我正在返回类型Either<Object, Data>
。
但是,如果我将该代码更改为:
public CompletionStage<Either<ErrorResponse, Data>> modifyData() {
CompletableFuture<Either<ErrorResponse, Data>> future = new CompetableFuture<>();
CompletableFuture.runAsync(() -> {
getData()
.thenCompose(d -> future.complete(Either.right(d)));
.exceptionally(e ->
future.complete(Either.left(ErrorResponse.create(e)))
});
return future;
}
然后它工作正常。为什么类型会丢失?
答案 0 :(得分:1)
你有
public CompletionStage<Either<ErrorResponse, Data>> modifyData() {
return getData()
.thenCompose(d -> CompletableFuture.completedFuture(Either.right(d)))
.exceptionally(e -> Either.left(ErrorResponse.create(e)));
}
thenCompose
是一种通用方法,但是您没有为Java提供足够的类型信息来推断您希望其类型参数U
绑定到Either<ErrorResponse, Data>
。对exceptionally
的调用(即使它是通用的)也无法将类型信息反馈给thenCompose
的调用。
目前,它会为Object
的第一个类型参数推断Either
。因此thenCompose
会返回CompletionStage<Either<Object, Data>>
。传播到exceptionally
。由于CompletionStage<Either<Object, Data>>
不是CompletionStage<Either<ErrorResponse, Data>>
,因此返回值的类型无效。
您可以通过提供显式类型参数来添加必要的类型信息。
public CompletionStage<Either<ErrorResponse, Data>> modifyData() {
return getData()
.<Either<ErrorResponse, Data>>thenCompose(d -> CompletableFuture.completedFuture(Either.right(d)))
.exceptionally(e -> Either.left(ErrorResponse.create(e)));
}
或更接近有问题的调用
public CompletionStage<Either<ErrorResponse, Data>> modifyData() {
return getData()
.thenCompose(d -> CompletableFuture.completedFuture(Either.<ErrorResponse, Data>right(d)))
.exceptionally(e -> Either.left(ErrorResponse.create(e)));
}
现在Java不必尝试猜测。它知道你的意思。
或者,我会使用CompletableFuture#handle
来处理异常情况。
return getData()
.handle((d, e) -> {
if (e == null) {
return Either.right(d);
}
return Either.left(ErrorResponse.create(e));
});
}
类型信息是自包含的。其余的主要是意见问题。