为什么两个scala运行环境会有不同的结果?

时间:2014-04-24 12:40:17

标签: scala

我正在阅读本书的第19.3节"在scala 2nd"中编程, 第431页中有一个代码段和一些描述:

注:FC17 x86_64 Scala-2.9.2

 class Cell[T](init: T) {
 private[this] var current = init
 def get = current
 def set(x: T) { current = x }
 }

我在两个不同的环境中修改了这个样本: 在第一篇文章中,我在Cell.scala文件中编写了以下代码

class A
class B extends A
class C extends B
class Cell[+T](init: T) {
private[this] var current = init
    def get = current
    def set[U >: T](x: U) {
    current = x.asInstanceOf[T]
    println("current " + current)
}
}

object Cell {
 def main(args: Array[String]) {
 val a1 = new Cell[B](new B)
 a1.set(new B)
 a1.set(new String("Dillon"))
 a1.get
}
}

并使用以下命令,并没有得到任何错误:

[abelard <at> localhost lower-bound]$ scalac Cell.scala
[abelard <at> localhost lower-bound]$ scala -cp . Cell
current B <at> 67591ba4
current Dillon
Dillon
[abelard <at> localhost lower-bound]$ 

在第二个,我直接在REPL下编写代码:

 scala> class Cell[+T](init: T) {
 | private[this] var current = init
 | def get = current
 | def set[U >: T](x: U) {current = x.asInstanceOf[T]
 | }}
defined class Cell

scala> val a1 = new Cell[B](new B)
a1: Cell[B] = Cell <at> 6717f3cb
scala> a1.set(new B)
scala> a1.set(new String("Dillon"))
scala> a1.get

java.lang.ClassCastException: 
java.lang.String cannot be cast to B
at .<init>(<console>:25)
at .<clinit>(<console>)

根据我对协变和下限的理解, 我认为第二个结果是对的,但我不知道为什么 第一个没有抛出任何错误?

我知道我必须遗漏一些东西,我想要编译 错误作为第二个,我该怎么办?

1 个答案:

答案 0 :(得分:2)

您不会收到编译错误,因为在编译时没有问题。 ClassCastException是运行时异常。

您应该注意到在评估a1.get后发生异常,而不是在a1.set中执行强制转换时发生异常。更确切地说,当您尝试将该返回值分配给变量时会发生这种情况。

在您的第一个方案中,a1.get未分配给值。在您的第二个中,您将其分配给res0

等值

您可以通过在REPL中尝试以下内容来证明这是问题所在:

scala> a1.get
java.lang.ClassCastException: java.lang.String cannot be cast to B

scala> println(a1.get)
Dillon