9

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

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

public Void empty() {
    return null;
}
4

1 回答 1

9

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

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

在您的情况下,您需要忽略来自源 future 和 return 的值null,因为null它是 type 唯一可能的值Void。但是,编译器需要有一些提示,您的目标是 type 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对 a 的结果执行任何操作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>

于 2016-05-11T03:20:11.010 回答