2017-01-10 37 views
0

今天我試着在intellij思想中調試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 + =威爾瑪」,在我的感覺,就應該繼續下一行 - 「fred.friends + = barney」。但相反,它回到了讓我非常困惑的第一條線。有人可以解釋爲什麼會發生這種情況嗎?提前致謝!

回答

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吸氣對應於同一行在源代碼中:val fred = new Person("Fred")

因此,當調試器第一次在val fred = new Person("Fred")行停止時,它正在使用new Person("Fred")初始化專用字段,然後當它進入該行後,它正在執行合成的getter方法。