为什么Scala asIstance似乎被忽略了?

时间:2016-03-18 23:10:54

标签: scala

试试这个:

object Box {
  val stuff:Any = "something"
  def foo[T]():T = {
    val z = stuff
    println(s"z = $z   class = ${z.getClass.getName}")
    val y = z.asInstanceOf[T]
    println(s"y = $y   class = ${y.getClass.getName}")
    y
  }
}

println(Box.foo[Boolean]())

跑步时我得到输出:

z = something   class = java.lang.String
y = something   class = java.lang.String

所以即使东西是Any类型,它确实知道z(从stuff分配)是一个String。我显然试图把它转换为T,这在我的println语句中显然是布尔值。为什么这不会爆炸?为什么它认为y是一个字符串?

如果我将foo()中的T硬连接到布尔值,我会得到预期的失败输出:

z = something   class = java.lang.String
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean
    at scala.runtime.BoxesRunTime.unboxToBoolean(BoxesRunTime.java:85)
    ...

它完全忽略了我的.asInstanceOf [T]。为什么呢?

1 个答案:

答案 0 :(得分:1)

正如克里斯·马丁所说,这是因为类型擦除而发生的。但是在scala中,可以通过ClassTag

告诉编译器保存已擦除的类型

我稍微修改了你的代码,如果你运行它你会得到一个ClassCastException

object Box {
  val stuff: Any = "something"
  def foo[T](implicit ev: ClassTag[T]): T = {
    val z = stuff
    println(s"z = $z   class = ${z.getClass.getName}")
    val y = ev.runtimeClass.cast(z)
    println(s"y = $y   class = ${y.getClass.getName}")
    z.asInstanceOf[T]
  }
}
println(Box.foo[Boolean])