如何将一种类型的CompletableFuture转换为另一种类型?

时间:2016-05-11 02:40:38

标签: java completable-future

我目前将CompletableFuture<X>转换为CompletableFuture<Void>,如下所示,但我想知道是否有更好的方式。

@Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenApply(c -> empty());
}

public Void empty() {
    return null;
}

1 个答案:

答案 0 :(得分:7)

您有效地尝试将CompletableFuture的已完成值转换为Void类型的值。据推测,如果未来异常完成,您希望传播任何异常。

CompletableFuture为此基本转换提供了thenApply,但也可以使用其他方法。

在您的情况下,您希望忽略来源未来的值并返回null,因为nullVoid类型唯一可能的值。但是,您需要为编译器提供一些提示,并将其定位到Void类型。

通过为thenApply

的调用提供显式类型参数,可以显式
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).<Void> thenApply(c -> null);
}

或通过强制转换为lambda表达式中的相应类型

public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenApply(c -> (Void) null);
}

您的解决方案实现了相同的结果,因为已知该值的类型正确,但它涉及额外的方法调用

@Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenApply(c -> empty());
}

所有这些解决方案都会传播原始CompletableFuture的例外(如果有)。

感谢Luis,您也可以thenAccept使用Consumer无所事事:

public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
    return realChannel.write(engineToSocketData).thenAccept(c -> {}):
}

任何其他类型的行为都是相同的。 thenApply可让您对Function的结果执行任何CompletableFuture

例如,我可以拥有一个意味着完成String的未来,意味着转换为Integer

public static void main(String[] args) throws Exception {
    CompletableFuture<String> futureLine = CompletableFuture.supplyAsync(() -> "1234");
    CompletableFuture<Integer> theNumber = futureLine.thenApply(Integer::parseInt);
    System.out.println(theNumber.get());
}

thenApply接收完成的值,并通过将其传递给Integer#parseInt(String)的调用来对其进行转换。由于parseInt的返回类型为int,因此thenApply的返回类型会推断为CompletableFuture<Integer>