2012-01-12 26 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 
} 

プライベートコンストラクタはここで使用するのに適していますか?その場合、私は間違っていますか?

申し訳ありませんが重複している場合は、私は答えを探してみましたが、何を探したらいいのか分かりません!

public class MyClass 
{ 
    static { 
    //init 
    } 
} 

答えて

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

はい、単純に値を初期化するのであれば、これははるかに好ましい方法です。 –

3

は、静的初期化子を使用してください。コンストラクタはクラスのインスタンスnew MyClass()を呼び出す)を初期化しますが、静的ステートはインスタンスに属していないため、コンストラクタから初期化しないでください。クラスが最初にロードされたときに発生させたい初期化は、クラスレベルに配置されたstaticブロック内にある必要があります。

static { 
    populateMyMap(); 
} 

ただし、決して静的(グローバル)状態は使用しないでください。静的状態では、システムを厳重にテストするのが困難になります。インスタンスの状態よりも微妙な違いがあります(たとえば、クラスの負荷ごとに1つのコピーがあります)。

マップの代わりにインスタンスメンバーを作成することを検討してください。

8

いいえ、プライベートコンストラクタは、あなたが望むものではありません。

+0

これはまた、すべての静的メソッドをインスタンスメソッドとして書き直す必要があります。これは私の意見では良いことです。 – emory

0

これを達成するには2通りの方法があります。 1つは、 "populateMyMap"メソッドを静的初期化子(またはA.H.が提案するアプローチ)にすることです。その後、最初の静的呼び出しの前に実行されることが保証されます。これは通常、populateMyMapを実行するコストが目立たないほど小さいか、またはアプリケーションが実行されるたびにクラスの機能を使用することを前提としている場合、最も良い方法です。

「populateMyMap」を実行するとかなりの時間がかかり、アプリの実行に機能を使用しないか、実行を延期したいデータが必要になるまで、populateMyMapを実行して、不必要に起動時間を増加させないようにします。

2つ目の方法が必要な場合は、静的メソッドではなく構造を切り替えてシングルトンを使用する必要があります。メソッドとデータを非静的にし、そのメソッドを呼び出す前に各ユーザーにSingletonインスタンスを取得させます。 "private"コンストラクタで "populateMyMap"が呼び出されました。はい、私は知っている、シングルトンは悪い評判を持っていて、人々は常に "偽装の世界的な方法であるため、それらを避ける"と言いますが、静的メソッドは単なるグローバルメソッドです。あなたは何も失っていない。そして、あなたが必要とするまで、あなたが必要としない限り、populateMyMapを実行するコストを支払うことはありません。

警告:データ構造が不変でない場合、つまり初期化後に変更できる場合は、これらの構造を使用しないでください。

関連する問題