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

Dea*_*ler 9 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;
}
Run Code Online (Sandbox Code Playgroud)

Sot*_*lis 7

您实际上正在尝试将完成的值CompletableFuture转换为type的值Void。如果将来异常完成,大概想传播任何异常。

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

在您的情况下,您将要忽略源future中的值并返回null,因为这null是type的唯一可能值Void。但是,需要为编译器提供一些针对类型的提示Void

通过为显式调用提供显式类型参数来显式 thenApply

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

或通过在lambda表达式中强制转换为适当的类型来明确显示

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

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

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

所有这些解决方案都将传播origial的异常(如果有)CompletableFuture

谢谢路易斯,你也可以只使用thenAccept一个Consumer无所事事:

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

对于其他类型,其行为是相同的。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());
}
Run Code Online (Sandbox Code Playgroud)

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