将Scala Future转换为Java Future。

17

我有一个生成的Java接口,其中包含一个方法:

public Future<?> getCustomersAsync(AsyncHandler<Customer> asyncHandler);

我想使用Akka实现它。我写了以下代码:

override def getCustomerAsync(asyncHandler: AsyncHandler[Customer]): Future[_] = {
  myActorRef.ask(GetCustomer, system.actorOf(Props[Responder]))
}

问题在于ask返回的是scala.concurrent.Future[Any],而方法必须返回java.util.concurrent.Future[?]:
Error:(33, 17) type mismatch;
 found   : scala.concurrent.Future[Any]
 required: java.util.concurrent.Future[?]
    myActorRef.ask(GetCustomer, system.actorOf(Props[Responder]))
                  ^

我该如何进行这个转换?

3个回答

7

Scala 2.13 开始,标准库包含 scala.jdk.FutureConverters,它提供了将 Scala 转换为 Java 的 Future(反之亦然):

import scala.jdk.FutureConverters._

// val scalaFuture: scala.concurrent.Future[Int] = Future.successful(42)
scalaFuture.asJava
// java.util.concurrent.CompletionStage[Int] = <function1>

Java用户请注意,最好使用FutureConverters进行显式转换:
import scala.jdk.javaapi.FutureConverters;

// val scalaFuture: scala.concurrent.Future[Int] = Future.successful(42)
FutureConverters.asJava(scalaFuture);
// java.util.concurrent.CompletionStage[Int] = <function1>

请问您能否包含转换后的future如何处理取消的信息? - mirelon

5

由于Scala的Future没有提供中断或其他取消机制,因此将它们转换成其他形式并不实际。因此,通过中断或其他方法调用来取消未来没有直接的、可靠的方法。

因此,如果不需要取消,则最简单的解决方案是:

  def convert[T](x:Future[T]):java.util.concurrent.Future[T]={
    new concurrent.Future[T] {
      override def isCancelled: Boolean = throw new UnsupportedOperationException

      override def get(): T = Await.result(x, Duration.Inf)

      override def get(timeout: Long, unit: TimeUnit): T = Await.result(x, Duration.create(timeout, unit))

      override def cancel(mayInterruptIfRunning: Boolean): Boolean = throw new UnsupportedOperationException

      override def isDone: Boolean = x.isCompleted
    }
  }

但是,如果你仍然需要 cancel,一个残缺的解决方案如下所示:

此处提供了相关信息。但是我不建议使用它,因为这种方法不够稳定。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接