2017-01-10 2 views
0

Сегодня я попытался отладить программу scala в интеллектуальной идее, я встретил одно явление, которое я не могу понять. Программа выглядит следующим образом:Не могу понять процедуру отладки в scala в intellij idea

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 как частное поле и геттер.

Посмотрите на декомпилируемой байткод в 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.

Смежные вопросы