Reputation: 8425
Could anyone explain why that happens?
scala> def as[T](v: Any) = Try(v.asInstanceOf[T])
as: [T](v: Any)scala.util.Try[T]
scala> as[Int]("Hello")
res0: scala.util.Try[Int] = Success(Hello)
scala> res0.map(_ + 1)
res1: scala.util.Try[Int] = Failure(java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer)
It's not about boxing because you could use your own type instead of Int
and it behaves the same way.
Doesn't seem to be about by-name parameter either, because you could replace Try
with Option
and it will be the same.
I'm guessing it's about erasure, but maybe somebody could give a detailed explanation?
Upvotes: 1
Views: 61
Reputation: 55569
It's all in the scaladoc:
Note that the success of a cast at runtime is modulo Scala's erasure semantics. Therefore the expression
1.asInstanceOf[String]
will throw aClassCastException
at runtime, while the expressionList(1).asInstanceOf[List[String]]
will not. In the latter example, because the type argument is erased as part of compilation it is not possible to check whether the contents of the list are of the requested type.
So, because T
is erased, Try(v.asInstanceOf[T])
will not immediately throw a ClassCastException
, because as far as the JVM knows, you have a Try[Any]
. But as soon as you try to treat the contained type like an Int
, you trigger the exception.
Upvotes: 4