2012-01-12 83 views
4

我有一個類可以在類內保存的地圖上進行靜態方法,我希望地圖設置上課的時候被調用。我試過使用私人構造函數,但它沒有被調用。我的代碼的相關部分:構造一類的靜態方法

public class MyClass 
{ 
    private static final String KEYS = "ABC"; 
    private static final String[] DATA = {"AAA", "BBB", "CCC"}; 
    private static HashMap<Character, String> myMap; 

    private MyClass() { 
     System.out.println("Running constructor"); 
     populateMyMap(); 
    } 

    private static void populateMyMap() { 
     myMap = new HashMap<Character, String>(); 
     for (int i=0; i < KEYS.length; i++) { 
      myMap.put(KEYS.charAt(i), DATA[i]); 
     } 
    } 

    //various static methods 
} 

就是要在這裏使用了正確的事情私有構造函數,如果是這樣我在做什麼錯?

對不起,如果這是重複的;我試過尋找答案,但我不知道要搜索什麼!

回答

5

靜態初始化塊在其他幾個答案中已經提到。但實際上我在野外更頻繁地找到以下成語:

public class MyClass 
{ 
    private static HashMap<Character, String> myMap = createMyMap(); 

    private static HashMap<Character, String> createMyMap() { 
     HashMap<Character, String> myTmpMap = new HashMap<Character, String>(); 
     for (int i=0; i < KEYS.length; i++) { 
      myTmpMap.put(KEYS.charAt(i), DATA[i]); 
     } 
     return myTmpMap; 
    } 
} 
+0

是的,如果是簡單地初始化一個值,這是更好的選擇。 – 2012-01-12 18:03:05

3

使用靜態初始化:

public class MyClass 
{ 
    static { 
    //init 
    } 
} 
8

不,一個私有構造函數是不是你想要的。構造函數初始化您的類的實例(當您調用new MyClass()時),但靜態不屬於某個實例,因此不應從構造函數初始化。當第一次加載類時,您想要進行的初始化應位於放置在類級別的static塊中。

static { 
    populateMyMap(); 
} 

但是,你永遠不應該使用靜態(全局)狀態。靜態使系統難以測試,它比實例狀態更細緻(例如,每個類的負載都有一個副本),並且通常難以使​​線程安全。

考慮對你的地圖的實例成員類的代替。

+0

這也需要重寫所有的靜態方法作爲實例方法 - 在我看來這是一件好事。 – emory 2012-01-12 18:11:50

0

有兩種實現方法。一種是使「populateMyMap」方法成爲靜態初始化器(或A.H.所建議的方法)。然後保證在第一次靜態調用之前執行。這通常是最好的方法,假設運行populateMyMap的代價足夠小,不會被注意到,或者幾乎每次運行應用程序時都要使用類的功能。

另一種方法是如果運行「populateMyMap」需要花費大量時間,或者您可能不會使用某些應用程序執行的功能,或者您希望推遲執行填充我的地圖,直到需要數據,以免不必要地增加啓動時間。

如果第二種方法是你想要的,那麼你應該切換結構和使用單例,而不是靜態的方法是什麼。使方法(和數據)非靜態,並讓它們的每個用戶在調用方法之前獲得Singleton實例。在(私有)構造函數中調用「populateMyMap」。是的,我知道,單身人士的聲譽很差,人們總是說「避免它們,因爲它們只是變相的全局方法」,但靜態方法也只是全局方法。你什麼也沒有損失。這樣你就不需要支付執行populateMyMap直到(或除非)需要的代價。

警告:如果你的數據結構都不是一成不變的,即它們可以將其初始化後改變,那麼你可能不應該使用這些結構。