无法理解智能思维中 scala 中的调试过程

  • 本文关键字:scala 调试 过程 智能 scala
  • 更新时间 :
  • 英文 :


今天我试图用 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",在我看来,它应该继续到下一行 - "fred.friends += barney"。但取而代之的是,它回到了让我非常困惑的第一行。谁能解释为什么它发生这样?提前感谢!

体中的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")

因此,当调试器第一次停在行val fred = new Person("Fred")时,它正在使用 new Person("Fred") 初始化私有字段,之后当它转到该行时,它正在执行合成的 getter 方法。

最新更新