今天我尝试在intellij想法中调试scala程序,我遇到了一个我无法理解的现象。 该计划如下:
import java.io._
import scala.collection.mutable.ArrayBuffer
class Person(val name: String) extends Serializable {
val friends = new ArrayBuffer[Person]
// OK—ArrayBuffer is serializable
def description = name + " with friends " +
friends.map(_.name).mkString(", ")
}
object TestSec08 extends App{
val fred = new Person("Fred")
val wilma = new Person("Wilma")
val barney = new Person("Barney")
fred.friends += wilma
fred.friends += barney
wilma.friends += barney
barney.friends += fred
val out = new ObjectOutputStream(new FileOutputStream("test.obj"))
out.writeObject(fred)
out.close()
val in = new ObjectInputStream(new FileInputStream("test.obj"))
val savedFred = in.readObject().asInstanceOf[Person]
in.close()
savedFred.description
savedFred.friends.map(_.description)
}
然后我从第一行调试它,当它转到第4行,这是" fred.friends + = wilma",在我看来,它应该继续到下一行 - &# 34; fred.friends + = barney"。但不是那样,它又回到了让我非常困惑的第一行。任何人都可以解释为什么会这样发生吗?提前谢谢!
答案 0 :(得分:0)
val
声明在Scala中实现为私有字段和getter。
查看TestSec08
初始化的反编译字节码:
/* Initializing private field `fred` */
0: aload_0
1: new #95 // class Person
4: dup
5: ldc #102 // String Fred
7: invokespecial #105 // Method Person."<init>":(Ljava/lang/String;)V
10: putfield #78 // Field fred:LPerson;
/* Initializing private field `wilma` */
13: aload_0
14: new #95 // class Person
17: dup
18: ldc #107 // String Wilma
20: invokespecial #105 // Method Person."<init>":(Ljava/lang/String;)V
23: putfield #80 // Field wilma:LPerson;
/* Initializing private field `barney` */
26: aload_0
27: new #95 // class Person
30: dup
31: ldc #109 // String Barney
33: invokespecial #105 // Method Person."<init>":(Ljava/lang/String;)V
36: putfield #82 // Field barney:LPerson;
39: aload_0
/* Calling getter for field `fred` */
40: invokevirtual #111 // Method fred:()LPerson;
/* Getting the array of fred's friends */
43: invokevirtual #115 // Method Person.friends:()Lscala/collection/mutable/ArrayBuffer;
46: aload_0
/* Calling getter for field `wilma` */
47: invokevirtual #117 // Method wilma:()LPerson;
/* Adding wilma to fred's friends */
50: invokevirtual #123 // Method scala/collection/mutable/ArrayBuffer.$plus$eq:(Ljava/lang/Object;)Lscala/collection/mutable/ArrayBuffer;
如果您还查看行号表,您会注意到此方法的开头和fred
getter对应于源代码中的同一行:val fred = new Person("Fred")
。< / p>
因此,当调试器第一次在第val fred = new Person("Fred")
行停止时,它正在使用new Person("Fred")
初始化私有字段,当它转到该行之后,它正在执行合成的getter方法