2011-05-27 54 views
2

我有這個課程,比方說,Foo。它是extends JFrame,是一個單身人士。也就是說,它有兩個靜態字段:1)Foo的實例和2)ColorSwing中靜態成員的排序是否敏感?

這裏是一個Foo代碼片段:

public class Foo extends JFrame{ 
    private static final Color FOO_RED = new Color(155, 64, 69); 
    private static final Foo INSTANCE = new Foo(); 

    private Foo(){ 
     //do stuff 
    } 

    public static Foo getInstance(){ 
     return INSTANCE; 
    } 
} 

我也有另一個類,比方說,Launcher。這是負責啓動應用程序的主類。這是一個簡單的課程,它唯一的工作就是將構建Foo的任務委託給EDT

這裏是一個Launcher代碼片段:

public class Launcher{ 
    public static void main(String[] args){ 
     SwingUtilities.invokeLater((new Runnable(){ 
      @Override 
      public void run() 
      { 
       Foo.getInstance(); 
      } 
     })); 
    } 
} 

現在,這一切都工作得很好。 但是,當我切換Foo的字段排序(請參閱下面的)時,使用FOO_RED的組件不再繪製此顏色。

public class Foo extends JFrame{ 
    private static final Foo INSTANCE = new Foo(); //declared before Color 
    private static final Color FOO_RED = new Color(155, 64, 69); 

    private Foo(){ 
     //do stuff 
    } 

    public static Foo getInstance(){ 
     return INSTANCE; 
    } 
} 

所以,這引出了一個問題,確實靜態字段,當談到Swing物質的排序?

回答

5

如前所述,靜態字段的排序很重要。按它們出現的順序執行。

我會對這個例子做另一個改變。這會讓你的靜態字段順序不那麼重要。

更新:使用IDOH (Initialization on Demand Holder)模式使單線程安全。

private static class FooHolder { 
    private static final Foo INSTANCE = new Foo(); 
} 

public static Foo getInstance(){ 
    return FooHolder.INSTANCE; 
} 
+1

+1僅在第一次需要時初始化實例。 – Deelazee 2011-05-27 14:40:24

+0

+1,解釋了爲什麼我看到「古怪」的行爲,並提供了一個合理的解決方案。謝謝你,低音。 :) – mre 2011-05-27 14:46:04

+1

+1,但請刪除最後一個修飾符。 – Howard 2011-05-27 16:10:08

4

是的。訂購任何static字段/塊。


編輯: 首先,靜態字段被設置爲默認值(所以FOO_REDnull)。然後在靜態字段中出現的順序被初始化。因此可以在初始化之前觀察FOO_RED字段。

+3

@mre它不是特定於Swing。 – pickypg 2011-05-27 14:24:59

+0

所以既然'FOO_RED'用於'Foo'的構造,如果我構造'Foo'的一個實例之前我聲明'FOO_RED',它不會使用它?我對如何排序很重要,爲什麼沒有編譯時錯誤,甚至是運行時錯誤,有點困惑。 – mre 2011-05-27 14:26:44

+1

@mre:首先,靜態字段被設置爲其默認值(FOO_RED爲空)。那麼靜態字段將按其出現的順序進行初始化。因此可以在初始化之前觀察FOO_RED字段。 – 2011-05-27 14:39:16

1

排序對靜態字段很重要,因爲它們是從上到下進行初始化的。在你的情況下,切換順序會導致在FOO_RED初始化之前調用Foo()構造函數。因此,FOO_RED將在構造函數中使用null。這是合法的,但顯然對任何想要使用FOO_RED的控件都沒有用處。

+0

這很奇怪。似乎應該有一些「依賴」錯誤(編譯時或運行時)拋出。 – mre 2011-05-27 14:28:57

+1

@mre運行時我不認爲會工作,因爲它必須「向前看」才能看到該字段在初始化之前使用。我相信編譯器也不會捕獲它,因爲它假定所有靜態初始化器都將在任何實例構造函數之前運行。你基本上通過在靜態初始化塊中調用Foo()構造函數來「欺騙」它。如果這是一系列導致這種情況的方法調用,那麼檢查這種情況可能會變得非常複雜,因此它只是忽略它並愉快地使用空引用。 – dlev 2011-05-27 14:31:49