2017-05-12 12 views
-1

列挙型要素を常に宣言して初期化する必要があるため、Javaで列挙型要素を初期化する前に静的初期化を行うことはできません。列挙型要素の前の静的初期化

静的初期化がenum要素に依存しない場合、要素の後の実行順序は問題になりません。それ以外の場合、初期化がenum要素に依存する場合、これは問題を引き起こします。しかし、Java enumsはこの依存関係を満たすことができるvalues()メソッドを提供します。ただし、values()メソッドは毎回内部の静的配列をコピーするため、values()を呼び出すことはオーバーヘッドになる可能性があります。例えば

(ポストWhy can't enum's constructor access static fields?で編集):

例に見られるように
public enum Day { 
    SUNDAY("Sun"), MONDAY("Mon"), TUESDAY("Tue"), WEDNESDAY("Wed"), THURSDAY("Thu"), FRIDAY("Fri"), SATURDAY("Sat"); 

    private final String abbreviation; 

    private static final Map<String, Day> ABBREV_MAP = new HashMap<String, Day>(); 

    static 
    { 
     for(Day day:values()) 
      ABBREV_MAP.put(day.abbreviation, day); 
    } 
    private Day(String abbreviation) { 
     this.abbreviation = abbreviation; 
     //ABBREV_MAP.put(abbreviation, this); this is not valid 
    } 

    public String getAbbreviation() { 
     return abbreviation; 
    } 

    public static Day getByAbbreviation(String abbreviation) { 
     return ABBREV_MAP.get(abbreviation); 
    } 
} 

、iは静的初期化コードブロックを必要としない、私があった場合従って、コピーを行う()メソッドの値を呼び出しますenum要素の前にHashMapを初期化することができます。コンストラクターでコメントアウトされたコードで十分です。

私の質問は、enum要素の初期化の義務が最初に不必要なオーバーヘッドで終わることがあるため、このオーバーヘッドを排除することが可能かどうか、つまりenum要素の前に静的初期化を行うことが可能ですか?そうでない場合は、コードの読みやすさだけですか?私はenum要素を宣言することは、いくつかの答えに記載されている安全な初期化とは何も関係がないと仮定します。

この質問では、ほとんどの時間がそれほどではありませんが、少なくともそれは深い理解と多分ブレーンストーミングの価値があります。精神的なヨガとして

+2

この「オーバーヘッド」はほんのわずかです**マイクロ秒(おそらくそれ以下)であり、プログラムで1回しか実行されません。私はあなたのコードでパフォーマンスチューニングのためのより良い候補があると確信しています。 – assylias

+0

私は、それがとても簡単なのに、偉大なプログラミング言語から期待どおりに完璧ではないのはなぜですか?それとも、コードの読みやすさだけですか? – oak

+0

詳細を提供しているように見えるので、[質問の回答](http://stackoverflow.com/q/443980/135078)をチェックしてください。あなたの質問に十分かどうかわからないので、私は再投票する投票。 –

答えて

1

上記のJoop Eggenの答えは、静的な内部クラスを使用するように促してくれました。明らかな回避策とトリックですが、このオーバーヘッドを排除することは不可能ではないことを示しています。 enum要素それはいいブレインストーミングだった。

、静的ブロックが削除され、オーバーヘッドが解消される値のテーブルとコンストラクタのために次のように私の最終的なコードは次のようになります静的初期化はクラスの最初の使用時に発生するため

//HashMap in inner class 
public static class InnerMap 
{ 
    private static final Map<String, Day> ABBREV_MAP = new HashMap<String, Day>(); 
} 
//Constructor 
private Day(String abbreviation) { 
    this.abbreviation = abbreviation; 
    InnerMap.ABBREV_MAP.put(abbreviation, this); 
} 

これは、動作この場合、内部クラス。

1

は、コンパイラがを行うために持っているものだと思う):

public enum Day { 

    SUNDAY(A.Sun), MONDAY(A.Mon), TUESDAY(A.Tue), 
    WEDNESDAY(A.Wed), THURSDAY(A.Thu), FRIDAY(A.Fri), SATURDAY(A.Sat); 

    private enum A { 
     Sun(Day.SUNDAY), Mon(Day.MONDAY), Tue(Day.TUESDAY), Wed(Day.WEDNESDAY), 
     Thu(Day.THURSDAY), Fri(Day.FRIDAY), Sat(Day.SATURDAY); 

     private final Day day; 

     A(Day day) { 
      this.day = day; 
     } 
    } 

    private final A abbrev; 

    Day(A abbrev) { 
     this.abbrev = abbrev; 
    } 

    public static Day getByAbbreviation(String abbreviation) { 
     return A.valueOf(abbreviation).day; 
    } 
} 

あまりにもひねくれました。

+0

組み込みのvalueOfメソッドが内部的にHashMapを使用すると、オーバーヘッドがキャンセルされます。しかし、要素にアクセスするときにHashMap以上のコストがかかる可能性があります。しかし、このような通常の内部クラスを使用し、その内部にHashMapを実装できるという考えを私に与えました。このオーバーヘッドを排除することは不可能だと私は考えていました。内部静的クラスは、静的初期化の回避策になります。あなたのブレーンストーミングに感謝します! – oak

+0

私はコードを変更しました。私の答えをチェックしてください! – oak

+0

実際に列挙型を3文字にトリミングすると、既にそれが行われています。 ;) –

関連する問題