在intellij想法中无法理解scala中的调试过程

时间:2017-01-10 06:23:20

标签: 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",在我看来,它应该继续到下一行 - &# 34; fred.friends + = barney"。但不是那样,它又回到了让我非常困惑的第一行。任何人都可以解释为什么会这样发生吗?提前谢谢!

1 个答案:

答案 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方法