2017-01-02 8 views
0

Javaで列挙型のようにC++を実装したいので、staticフィールドをカウンタとして使用したいと思います。これは私の現在のソリューションです:Java静的カウンタ付き列挙型

public enum ETest 
{ 
    Test1(2), 
    Test2, 
    Test3, 
    Test4(7), 
    Test5; 

    private static class CounterHolder 
    { 
     private static int mCount = 0; 
    } 

    ETest() 
    { 
     mValue = CounterHolder.mCount; 
     CounterHolder.mCount++; 
    } 

    ETest(int pValue) 
    { 
     CounterHolder.mCount = pValue; 
     mValue = CounterHolder.mCount; 
     CounterHolder.mCount++; 
    } 

    public int toInt() 
    { 
     return mValue; 
    } 

    private final int mValue; 
} 

私が取得する必要があり、上記のコードから: Test1.toInt() - > 2、Test2.toInt() - > 3、Test3.toInt() - > 4、TEST4 .toInt() - > 7、Test5.toInt() - > 8

このコードはテスト済みのAndroid Java VMでうまく動作しますが、有効なJavaコードであれば、すべて正常に動作するかどうかわかりませんAFAIK enumは静的フィールドの前に初期化されているため、有効なJavaのVMは静的フィールドの初期化のように見えますが、この場合静的フィールドは正常に動作します(入れ子クラスなし、単純静的フィールドは機能しません)。

敬具、すべての準拠したJVMで期待どおりのコードは動作するはずですのでETestが初期化される前に はPatryk

+0

ドン」をC++構造体をJavaに変換しようとしないでください。 Javaの列挙型は、単純なC++スタイルの値のコンテナとして悪用されるほど強力です。 –

+0

私はかなりそのコードがコンパイルされないことを確信しています - 質問で実際のコードを使用してください... –

+0

@GyroGearlessまあ、このコードは、私が要求に応じて初期化を使用したためコンパイルします。他のJVM上の実行時の問題 – nadro

答えて

0

CounterHolderは常にロードされ、初期化されます。 JLSでクラス初期化の詳細を読むことができます(それと同等の文書がアンドロイド用であるかどうかはわかりませんが、それらは非常によく似ています)。

  • [...]

    • Tによって宣言された静的フィールド:クラスまたはインタフェースタイプTは、以下のいずれかの最初の発生直前に初期化される

      :特にフィールドが定数変数ではありません。

    ので遅くとも、CounterHolderクラスはETest実行の最初のコンストラクタの前にロードされ、初期化されます。しかし、スタイルの観点から、おそらくちょうど書くためにきれいになること

    注:

    enum ETest { 
        Test1(2), 
        Test2(3), 
        Test3(4), 
        Test4(7), 
        Test5(8); 
    } 
    
  • 0

    実はそんなに

    public enum TestEnum { 
        Test1(2), 
        Test2, 
        Test3, 
        Test4(7), 
        Test5; 
    
        private static Map<TestEnum, Integer> map = new HashMap<>(); 
    
        static { 
         int counter = 0; 
         for (TestEnum enun : TestEnum.values()) { 
    
          counter = Math.max(counter, enun.value); 
          if (enun.value == 0) { 
           counter++; 
          } 
          map.put(enun, counter); 
         } 
        } 
    
        private int value; 
    
        TestEnum() { 
         value = 0; 
        } 
    
        TestEnum(int pValue) { 
         value = pValue; 
        } 
    
        public int toInt() { 
         return map.get(this); 
        } 
    } 
    

    のように列挙型の内側にMapを使用して簡単にそれを行うことができますし、ここに結果を印刷する機能があります。

    for (TestEnum anEnum : TestEnum.values()) { 
        System.out.println(anEnum.name() +" = "+ String.valueOf(anEnum.toInt())); 
    } 
    

    とou TPUTは次のとおりです。

    Test1 = 2 
    Test2 = 3 
    Test3 = 4 
    Test4 = 7 
    Test5 = 8 
    

    TIP:チェック何かがordinalと呼ばれ、それが列挙定数の序数(初期定数はゼロの序数が割り当てられ、その列挙型の宣言、内の位置)です。アンドロイドで

    +0

    ありがとう、しかし、私はHashMapに関連するオーバーヘッドをこの種の単純なタスクにしたくありません。 – nadro

    +0

    鍵の型が 'enum'型の場合、HashMapに関連するオーバーヘッドを避けるために、' EnumMap'があります。もちろん、 'value'は' final'ではないので、静的イニシャライザは地図を塗りつぶすのではなくゼロ値を上書きすることができ、 'toInt'は以前と同じように動作します... – Holger

    0

    、ベストプラクティスは、主な理由のために列挙型を使用することがないようであるアンドロイドのドキュメントに基づいて、抗最適化のパフォーマンスです:

    列挙型は、多くの場合、静的 の2倍のメモリよりも多くを必要とします定数。 Androidではenumを厳密に使用しないでください。反対側のAndroid目的で

    ソリューション型DEF注釈:

    @IntDefアノテーションはあなたが基本的に はあなたが有効な整数に 定数を表し、別の注釈を作成する「のtypedef」を、作成することができますあなたはこの typedefアノテーションを使用してAPIを飾ります。ここで

    (日チェッカー...)それを使用する方法を、サンプル例です。 https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/

    そして、もっと知っての機能のためにあなたは、公式ドキュメント読むことができます: https://developer.android.com/studio/write/annotations.html#enum-annotations

    関連する問題