假设我有这个方法:
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;
}那么它工作得很好。为什么类型丢失了?
发布于 2017-07-21 02:38:53
你有
public CompletionStage<Either<ErrorResponse, Data>> modifyData() {
return getData()
.thenCompose(d -> CompletableFuture.completedFuture(Either.right(d)))
.exceptionally(e -> Either.left(ErrorResponse.create(e)));
}thenCompose是一个泛型方法,但是您没有提供足够的类型信息来推断您希望将其类型参数U绑定到Either<ErrorResponse, Data>。对exceptionally的调用(即使它是泛型的)也不能向thenCompose的调用反馈类型信息。
目前,它为Either的第一个类型参数推断Object。因此,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));
});
}类型信息是自包含的。剩下的主要是意见问题。
https://stackoverflow.com/questions/45221337
复制相似问题