以下函数是一些代码的一部分,我必须与一个特别讨厌的(如无类型的)Java API进行交互。它旨在安全地执行强制转换,其中上下文“知道”应该的类型,但我想确保在运行时某些未知边缘情况下我不会有错误的故障模式:
def safeCast[A](o: Any): Option[A] =
Try(o.asInstanceOf[A]).toOption
现在看看在REPL会话中使用它会发生什么:
scala> val testDouble: Double = 1.0
testDouble: Double = 1.0
scala> safeCast[Int](testDouble)
res0: Option[Int] = Some(1.0)
res0
声称其类型为Option[Int]
,但值为Some(1.0)
(即 - Some[Double]
)。如果我们尝试映射此选项,则会出现类强制转换异常。
此行为仅在多态safeCast
时发生。如果我们收紧特定类型:
def safeIntCast(o: Any): Option[Int] = Try(o.asInstanceOf[Int]).toOption
然后我们得到:
scala> safeIntCast(testDouble)
res1: Option[Int] = None
因此,多态性以某种方式与拳击(我怀疑??)或编译器问题(bug ??)进行交互。使用的编译器版本是2.12.2
有人可以为此提供解释吗?
答案 0 :(得分:2)
这是因为类型擦除,类型T在运行时是未知的。当您映射类型已知时(因为它已被评估)并且您正在获取ClassCastException。
但是你可以使用class标签在运行时获取类型:
import scala.reflect.ClassTag
import scala.util.Try
object Application extends App {
def safeCast[A](o: Any)(implicit ct: ClassTag[A]): Option[A] =
Try(ct.runtimeClass.cast(o).asInstanceOf[A]).toOption
}
答案 1 :(得分:1)
答案 2 :(得分:0)
对于泛型类型.asInstanceOf[A]
,没有A
这样的东西,它只是在运行时消失了:
$ echo 'class Demo { def safeCast[A](o: Any) = o.asInstanceOf[A] }' > test.scala
$ scalac test.scala
$ cfr test.scala
$ javap -c Demo
Compiled from "test.scala"
public class Demo {
public <A> A safeCast(java.lang.Object);
Code:
0: aload_1
1: areturn
public Demo();
Code:
0: aload_0
1: invokespecial #18 // Method java/lang/Object."<init>":()V
4: return
}