I currently convert my CompletableFuture<X>
to CompletableFuture<Void>
as shown below but I was wondering if there was a better way.
@Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenApply(c -> empty());
}
public Void empty() {
return null;
}
You're effectively trying to transform the completed value of your CompletableFuture
into a value of type Void
. Presumably you want to propagate any exception if that future was completed exceptionally.
CompletableFuture
provides thenApply
for this basic transformation, but other methods can also be used.
In your case, you'll want to ignore the value from the source future and return null
, since null
is the only possible value for the type Void
. However, there needs to be some hint for the compiler that you're targeting the type Void
.
Either be explicit by providing an explicit type argument to the invocation of thenApply
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).<Void> thenApply(c -> null);
}
or be explicit by casting to the appropriate type in the lambda expression
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenApply(c -> (Void) null);
}
Your solution achieves the same result, since the value is known to be of the correct type, but it involves an extra method invocation
@Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenApply(c -> empty());
}
All of these solutions will propagate the exception, if any, of the origial CompletableFuture
.
Thank you to Luis , you could also just use thenAccept
with a Consumer
doing nothing:
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenAccept(c -> {}):
}
The behavior is the same for any other type. thenApply
lets you perform any Function
on the result of a CompletableFuture
.
For example, I can have a future that's meant to complete with String
that's meant to be converted to an 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
receives the completed value and transforms it by passing it to an invocation of Integer#parseInt(String)
. Since parseInt
has a return type of int
, the return type of thenApply
is inferred to CompletableFuture<Integer>
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.