Scala 2.10中的新行为

时间:2012-12-28 14:32:29

标签: scala scala-2.10

这里有两个REPL会议(灵感来自this question,虽然我的问题不同):

Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def ignore(it: String) = 42
ignore: (it: String)Int

scala> ignore(null.asInstanceOf[Nothing])
res0: Int = 42

Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def ignore(it: String) = 42
ignore: (it: String)Int

scala> ignore(null.asInstanceOf[Nothing])
java.lang.NullPointerException
        at .<init>(<console>:9)
        at .<clinit>(<console>)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

唯一的区别是第一个是Scala 2.9.2,第二个是2.10.0。

有人能指出导致这种新行为的2.10中的变化吗?

我知道向Nothing投射是一件愚蠢的事情,答案可能是“这是所有未定义的行为所以只是停止这样做”,但它看起来像是可能发生的事情对升级者有影响,我不记得碰到任何可以解释这一点的变化的讨论。

3 个答案:

答案 0 :(得分:5)

由于Scala对null选项的None处理方式不同,即使null值为Nothing也存在问题,因此{的实例应该为零{1}},根据您的使用方式,不是一个可能会或可能不会中断的实例。

因此,我看不出旧的行为是什么,只不过是一个错误。应该在发行说明中说明它已被修复,但是依靠Nothing来执行任何事情保存抛出异常与类型理智完全相反,我认为没有更多需要。 (事实上​​,我甚至不认为需要发布说明。)

答案 1 :(得分:3)

这看起来只是控制台的问题,而不是语言问题。如果你运行这个调用完全相同的方法的小应用程序,scala 2.10没有问题。

object Test extends App {
  override def main(args: Array[String]) {
    println(takesString(null.asInstanceOf[Nothing]))
  }

  def takesString(a: String) = 42
}

要简化上面的示例,您只需输入

即可
null.asInstanceOf[Nothing]

并且控制台会给你同样的错误。 我认为它与打印出类型有关。

更新:看起来我不小心碰到了2.9.2。正如作者在评论中指出的那样,仍然作为2.10 RC5中的脚本失败。

答案 2 :(得分:2)

我知道你没有期待答案“这是所有未定义的行为,所以(...)”,但是当你添加“可能对升级者产生影响的东西”时,我必须记住(即使它很明显)根据自己的定义,人们不能依赖或期望任何具有未定义行为的事物的结果

在您提到的特定情况下,我认为它不是未定义的行为:它应该抛出异常。 NothingNull的子类,而不是相反 - 我的第一个期望,即没有测试,就是null.asInstanceOf[Nothing]行会抛出ClassCastException,{{1 }}不是null。但是,您可以看到Nothing是一个特殊实例(就像在Java中一样)。尝试运行:

null

我的猜测是因为内部scala> "aaa".asInstanceOf[Nothing] java.lang.ClassCastException: java.lang.String cannot be cast to scala.runtime.N othing$ at .<init>(<console>:8) at .<clinit>(<console>) 调用obj.asInstanceOf[T]以便在运行时检查强制转换。当调用obj.getClass()上的任何方法抛出null时,会在NullPointerException之前抛出该异常。

回到你的具体问题,似乎Scala 2.9.2以(非常)特殊的方式处理特定情况。再运行一些测试:

ClassCastException

除了您的情况,您可以看到始终正在评估参数。 Scala 2.10绝对具有最一致的行为。但是,此问题不应影响任何升级到Scala 2.10的开发人员;我无法看到scala> ignore(3.asInstanceOf[String]) java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stri ng at .<init>(<console>:9) at .<clinit>(<console>) scala> ignore({ println("test"); "aaa" }) test res6: Int = 42 是正确代码的任何情况。