一些带有asInstanceOf的构造函数

时间:2011-08-03 09:57:01

标签: scala option lazy-evaluation

当我写recent answer时,我也尝试以更“功能”的方式解决问题,但遇到了以下问题:

scala> "1".asInstanceOf[Int]
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
        ...
scala> Some("1".asInstanceOf[Int])
res29: Some[Int] = Some(1)
而且只有
scala> res29.get
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source)
        ...

看起来Some的论证是懒惰评估的,但我在the sources中找不到任何线索。 Some构造函数中的x参数是strict。

为什么有些asInstanceOf会有这么奇怪的行为?

1 个答案:

答案 0 :(得分:2)

构造函数参数未被延迟评估。您收到错误的那一刻是REPL尝试显示结果的时刻,作为Int(unboxToInt)。如果您进一步查看堆栈,可以找到scala_repl_result

我认为问题是asInstanceOf[Int]在运行时根本没有检查。我不知道它是否符合规范(对于值类型)或bug。编译器被欺骗接受"1"Int(或盒装Int),等待asInstanceOf隐含的运行时检查,但不会发生。

由于Option / Some不是专门的,因此在运行时只有Some[Object]。因此,对于JVM,调用构造函数new Some(Object o),它在代码验证和运行时被接受。 toString(由新建的Some上的REPL调用)在通用代码中,其中T也被视为Object(或AnyRef),因此它可以工作,{{{ 1}}显示。另一方面,每次在编译器知道泛型参数的类型的上下文中访问值时,都会在代码中插入强制转换(在值类型的情况下为+ unboxing)。这是它实际失败的时候(这里REPL在显示之前进行拆箱)。

编辑这是在Scala 2.8.1中。根据@incrop上面的评论,现在已经修复了。