【问题标题】:why are there different results in two scala running environments?为什么在两个 scala 运行环境中有不同的结果?
【发布时间】:2014-04-24 12:40:17
【问题描述】:

我正在阅读“scala 2nd 编程”一书的第 19.3 节, 431页有一个sn-p代码和一些描述:

注意: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>)

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

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

【问题讨论】:

    标签: scala


    【解决方案1】:

    您不会遇到编译错误,因为在编译时没有问题。 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
    

    【讨论】:

    • 谢谢!我明白了一点。我还有一个问题:
    • 谢谢!我明白了一点。我还有另一个问题:为什么 res0 的类型(如您所想)是 B 类?而函数set()中“current = x.asInstanceOf[T]”之后的current类型可以是我的示例中的String等任何类型?
    • @abelard20008 你的 get 和 current 都是 T,这是 Cell[B] 的 B。你的任务说你知道 x 也是一个 T,不管 T 碰巧是什么。当然,也许你错了。您可能已将方形钉塞入圆孔中。圆孔是Object。
    • @som-snytt 谢谢!为了验证电流的类型,我在 current = x.asInstanceOf[T] 之后执行了 println(current.getClass.getName) ,我得到了两个不同的结果:(1)current 的类型在 a1.set(new B) 之后是 B (2)current' s 类型是 a1.set("Dillon") 之后的 java.lang.String 。所以我认为current的类型可以改变吗?我一定错过了什么!
    • @abelard20008 这就是编译时的静态类型和运行时可用的任何类型信息之间的区别。 CCE 表示你说 asInstanceOf 时撒了谎,结果证明运行时类型是错误的。所以避免使用 asInstanceOf。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多