2012-10-24 48 views
3

我知道Singleton模式有很多問題。但是,在這裏我想知道的關於輸出的內容也可能涵蓋Java中「靜態」的工作原理。在Singleton程序中使用和流動Static語句

public class Singleton { 
    private static Singleton currentSingleton = new Singleton(); 

    public static Singleton getSingleton() { 
     return currentSingleton; 
    } 

    private Singleton() { 
     System.out.println("Singleton private constructor..."); 
    } 

    public static void main(String[] args) { 
     System.out.println("Main method..."); 
    } 

}

這是從運行代碼的輸出...

辛格爾頓私有構造...
主要方法...

當我調試這個代碼,控制先行 System.out.println("Singleton private constructor...")並打印。 (私有靜態變量currentSingleton仍是空在這一點上)
便去排隊
private static Singleton currentSingleton = new Singleton(); ,然後初始化私有變量。然後最後,它轉到main()方法並打印。

我的問題是:

  1. 爲什麼它首先打印「辛格爾頓私有構造......」這是私人的構造函數。 我想控制應該首先轉到main()方法,因爲它是入口點。另外我不會在任何地方創建任何實例(變量初始化除外)。
  2. 後來它進入靜態變量實例線(currentSingleton = NULL在這一點上)
    private static Singleton currentSingleton = new Singleton(); 雖然currentSingleton這裏得到一個值,爲什麼構造函數不會再次叫什麼名字?

主要是我想知道這個程序的控制流。

回答

3

你不能調用的主要方法在課堂上,直到它已經被正確初始化(即靜態字段和靜態塊已被評估)。初始化時,通過調用私有構造函數創建單例實例。稍後調用主方法。

有問題的類有一個靜態字段到您assing的值。由於該字段是靜態的,因此必須在可以在任何上下文中使用該類之前對其進行初始化,也就是說,它必須接收一個值。在這種情況下,它的值恰好是同一類的一個實例。這是在類初始化期間觸發你的私有構造器的原因。

如果你想深入研究過程,並更好地理解它,請參閱Java Laguage Specification。更具體地在12.4 Initialization of Classes and Interfaces部分,您會發現更多詳細信息。

+1

澄清:'直到它已經被正確initialized' - >'it'在這裏是*類對象*,而不是*類實例*。 – amit

+0

好吧,第一類應該正確初始化,所以它會調用行private static Singleton currentSingleton = new Singleton();然後它應該調用構造函數並打印語句。但是當我調試它時,控制首先進入私有構造函數,打印然後去初始化私有靜態變量。這就是爲什麼我感到困惑。 – Girish

+1

@amit有問題的類有一個靜態字段,您可以爲其賦值。由於該字段是靜態的,因此必須使用該類進行初始化,也就是說,它必須接收一個值。在這種情況下,它的值恰好是同一類的一個實例。這是在類初始化期間觸發你的私有構造器的原因。 –

4

每當控制涉及到任何類的第一次,所有的靜態初始化首先發生。這就是爲什麼你的靜態對象通過調用它的構造函數在其他任何東西之前被實例化的原因。

2

控制到達main()方法之前,類需要被初始化。由於您在聲明中內聯初始化currentSingleton,因此此類初始化在類加載期間發生在main()之前。

2

你還是把它聲明爲接口final

private static final Singleton currentSingleton = new Singleton(); 
  1. final類變量和字段,其值是編譯時間常數初始化

回答您的兩個問題從JLS#8.3.2. Initialization of Fields

如果聲明符對於類變量(即靜態字段),則在初始化類時(§12.4.2),將對變量初始值設定項進行評估並執行一次賦值。

3

類被加載並且通過JVM的類加載器第一次初始化。 JVM在初始化時掃描類(Singleton),並在初始化時初始化位於第一行的靜態變量。該變量調用構造函數並在其中打印行。一旦類被初始化,它將調用main方法,並在其中打印語句。

2

new Singleton()語句是第一個被執行的語句,因爲必須初始化currentSingleton靜態字段;這意味着分配正在創建的Singleton對象的內存,並且在將結果對象分配給字段變量之前執行其構造函數。 這是在作業前執行System.out.println("Singleton private constructor...");一行的原因。 此外靜態字段初始化爲類被引用並調用Singleton類的主要功能是指參照它,這是初始化的主要方法之前執行的原因,一旦發生。