I'm reading the Akka Futures Guide and I see this sentence:
Also note that the Future returned by an Actor is a Future[Any] since an Actor is dynamic. That is why the asInstanceOf is used in the above sample. When using non-blocking it is better to use the mapTo method to safely try to cast a Future to an expected type
Why is mapTo better to use than asInstanceOf for a non-blocking Future?
The problem with asInstanceOf
here is, that it will simply cast to anything you want
scala> val f = future { 2 }
f: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@69b28a51
scala> f.asInstanceOf[Future[String]]
res9: scala.concurrent.Future[String] = scala.concurrent.impl.Promise$DefaultPromise@69b28a51
scala> f.asInstanceOf[Future[List[String]]]
res10: scala.concurrent.Future[List[String]] = scala.concurrent.impl.Promise$DefaultPromise@69b28a51
scala> res10.value
res15: Option[scala.util.Try[List[String]]] = Some(Success(2))
Because of the type erasure the jvm does not know the concrete inner type of the value. If you use mapTo
instead, it will cast directly on the value, once it is available and in case of a non-matching type, you will get a failed future back.
scala> f.mapTo[List[String]]
res11: scala.concurrent.Future[List[String]] = scala.concurrent.impl.Promise$DefaultPromise@2828afbb
scala> res11.value
res14: Option[scala.util.Try[List[String]]] = Some(Failure(java.lang.ClassCastException:
Cannot cast java.lang.Integer to scala.collection.immutable.List))
It's not so much that mapTo
is better in that case, as that asInstanceOf
is unavailable: their example with asInstanceOf
uses it to cast the result from Any
to String
, but with a non-blocking future, you don't have the result yet, even as an Any
. Instead, you have a Future[Any]
, and you need to use its mapTo
method to wrap it up as a Future[String]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With