Scala在通用函数中进行类型转换的奇怪行为

时间:2015-09-26 00:26:44

标签: scala reflection casting type-erasure

有人可以解释为什么会这样吗?

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)

这不是拳击,因为你可以使用自己的类型而不是Int,它的行为方式相同。

似乎也不是关于by-name参数,因为您可以将Try替换为Option,它将是相同的。

我猜它是关于擦除的,但也许有人可以给出详细解释?

1 个答案:

答案 0 :(得分:4)

全部在scaladoc

  

请注意,演员在运行时的成功是模Scala的擦除语义。因此,表达式1.asInstanceOf[String]将在运行时抛出ClassCastException,而表达式List(1).asInstanceOf[List[String]]则不会。在后一个示例中,因为类型参数作为编译的一部分被删除,所以无法检查列表的内容是否是所请求的类型。

因此,由于T被删除,Try(v.asInstanceOf[T])不会立即抛出ClassCastException,因为就JVM而言,您有一个Try[Any]。但是,只要您尝试将包含的类型视为Int,就会触发异常。