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
}

ここでプライベートコンストラクターを使用するのは正しいことですか?もしそうなら、私は何を間違っていますか?

これが重複している場合は申し訳ありません。回答を検索してみましたが、何を検索すればよいかわかりません。

4

4 に答える 4

8

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

static {
   populateMyMap();
}

ただし、静的 (グローバル) 状態は使用しないでください。静的状態は、システムのテストを非常に困難にし、インスタンス状態よりも微妙であり (たとえば、クラスのロードごとに 1 つのコピーがある)、通常はスレッド セーフにするのが難しくなります。

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

于 2012-01-12T17:41:47.943 に答える
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;
    }
}
于 2012-01-12T17:45:40.013 に答える
3

静的初期化子を使用します。

public class MyClass
{
    static {
    //init
    }
}
于 2012-01-12T17:41:03.260 に答える
0

これを実現するには 2 つの方法があります。1 つは、「populateMyMap」メソッドを静的初期化子 (または AH によって提案されたアプローチ) にすることです。その後、最初の静的呼び出しの前に実行されることが保証されます。populateMyMap を実行するコストが気付かれないほど小さいか、またはアプリケーションを実行するたびにほぼ毎回クラスの機能を使用する場合は、通常、これが最善の方法です。

別のアプローチは、「populateMyMap」の実行にかなりの時間がかかる場合に使用するものであり、アプリの一部の実行では機能を使用しないか、データが返されるまで populateMyMap の実行を延期します。起動時間を不必要に増加させないために必要です。

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

警告: データ構造が不変でない場合、つまり初期化後に変更できる場合は、おそらくこれらの構造を使用すべきではありません。

于 2012-01-12T18:08:53.793 に答える