2017-02-15 22 views
3

可有人請敷衍我詳細下列情況下,這將是,如果解釋爲包括三種情況下的內存分配和引用更方便:爲什麼以下案件的執行流程不同?

  1. 如何流動在三種情況下執行?
  2. 爲什麼這三種情況下的流程不同?
  3. 儘管兩個類之間存在循環依賴關係,但爲什麼僅在單個案例1失敗時才執行案例1?

情況下,一個

namespace CircularDependency_1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      A a = new A(); 
      Console.WriteLine("executed"); 
      Console.ReadLine(); 
     } 
    } 

    public class B 
    { 
     public static A a = new A(); 

     public B() 
     { 

      Console.WriteLine("Creating B"); 
     } 
    } 

    public class A 
    { 
     public static B b = new B(); 

     public A() 
     {   
      Console.WriteLine("Creating A"); 
     } 
    } 
} 

輸出

Creating A 
Creating B 
Creating A 
executed 

情況下,兩個

namespace CircularDependency_1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      A a = new A(); 
      Console.WriteLine("executed"); 
      Console.ReadLine(); 
     } 
    } 

    public class B 
    { 
     public static A a; 

     public B() 
     { 
      a = new A(); 
      Console.WriteLine("Creating B"); 
     } 
    } 

    public class A 
    { 
     public static B b; 

     public A() 
     {  
      b = new B(); 
      Console.WriteLine("Creating A"); 
     } 
    } 
} 

OUTPUT 由於StackOverflowException,進程終止。

情況下爲三個

namespace CircularDependency_1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      A a = new A(); 
      Console.WriteLine("executed"); 
      Console.ReadLine(); 
     } 
    } 

    public class B 
    { 
     public A a; 

     public B() 
     { 
      a = new A(); 
      Console.WriteLine("Creating B"); 
     } 
    } 

    public class A 
    { 
     public B b; 

     public A() 
     {  
      b = new B(); 
      Console.WriteLine("Creating A"); 
     } 
    } 
} 

OUTPUT 過程由於StackOverflowException終止。

+0

你爲什麼包含'java'標籤? – SomeDude

+0

@svasa我認爲這個問題更多的是OOPS而不是面向語言 –

+1

我投票結束這個問題作爲題外話,因爲[問題要求作業幫助必須包括你迄今爲止所做的工作的總結問題以及你解決問題的難點描述](http://stackoverflow.com/help/on-topic)。 – RealSkeptic

回答

2

@多才多藝,你很接近,但不正確。第一種情況執行和其他兩種情況失敗的原因不僅僅是因爲對象是在構造函數內部還是在類內部(構造函數之外)創建的。爲了證明這一點,請嘗試分別在BA類(第一種情況)中使ab字段不是靜態的;你會發現它會失敗,即使這些對象是在構造函數之外創建的。

由於@Versatile解釋的原因,案例2和3失敗。 由於static成員,因此執行了第1種情況。 讓我們來看看流程:

Main方法中,行A a = new A()開始創建a對象。在此過程中,將創建類B的對象,因爲行public static B b = new B() - 由於B類的主體中的行public static A a = new A(),該行將開始創建類A的另一個對象。現在,這裏出現了魔法(不會觸發循環依賴)。這條線,public static A a = new A()將開始創建A類的另一個對象,在創建此對象時,它不會創建B類的另一個對象,因爲它是A的靜態成員,並且它已創建。我們知道,類的靜態成員在類的所有實例之間共享。因此,它不會觸發創建類B的另一個對象。總的來說,我們最終得到三個類的實例:AB,A

UPDATE

有趣的觀察,在第一種情況下,如果我們初始化構造函數中的靜態成員會發生什麼。儘管AB類聲明瞭靜態成員,但由於循環依賴性,執行將失敗。這是因爲靜態成員在執行構造函數之前未被初始化。

+0

感謝您指出。我認爲靜態的使用很明顯,對象只會創建一次,而且因爲它在該行被分配了新的內存,因此它不會進入遞歸調用。 – Versatile

1

1.這三種情況下的流程是如何執行的? 首先調用static void Main(),然後調用對象A的構造函數,因爲代碼行A a = new A();

2.爲什麼這三種情況下的流程不同?

3.雖然兩個類之間存在循環依賴關係,但爲什麼僅在第一種情況下才執行第一種情況,而其餘的情況都是失敗的?

由於相同的原因,觀察到上述兩種情況。如果仔細觀察,則按如下方式分配內存。 Case1中的類而不是構造函數。即

public class A 
{ 
    public static B b = new B(); 
} 

此外的對象是靜態的,所以它將被創建只有一次,因爲這是創建一次,其在同一行分配存儲器獲取僅執行一次。

情況2和情況3:存儲器到對象A和B在構造器中分配,即在A的構造器中,存儲器被分配給B,而在B的構造器中,存儲器被分配給A,這導致調用相應的類一次又一次地構造函數,直到拋出一個異常。

相關問題