2017-01-02 27 views
0

我想在Java中像枚舉一樣實現C++,所以我想使用靜態字段作爲計數器。這是我的當前的解決方案: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是在靜態字段之前初始化的,但是在這種情況下,它看起來像使用靜態字段的嵌套類的初始化工作正常(沒有嵌套類,簡單靜態字段不起作用)。

最好的問候, Patryk

+0

別嘗試將C++結構轉換爲Java。 Java引入強大的方式被濫用爲簡單的C++風格的值容器。 –

+0

我敢肯定,該代碼將不會編譯 - 請使用問題真正的代碼... –

+0

@GyroGearless那麼這個代碼編譯,因爲我用按需初始化,我只是不知道這會不會造成在其他JVM上運行時出現問題。 – nadro

回答

0

CounterHolder將永遠被載入和ETest之前初始化被初始化,以便您的代碼應工作按預期在所有兼容的JVM。您可以在JLS中閱讀關於類初始化的更多信息(不確定Android的等效文檔是什麼,但我期望它們的語句非常相似)。特別是:

類或接口類型T將立即以下中的任一個的第一次出現之前被初始化:

  • [...]
  • 靜態字段由T聲明被使用並且該字段不是一個常量變量。

因此,在最新的CounterHolder類將被加載並運行ETest的第一個構造函數初始化之前。

不過請注意,從風格的角度來看,它很可能是清潔劑只寫:

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

其實你可以很容易地使用Map枚舉內,像這樣

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); 
    } 
} 

和做這裏是打印結果的功能

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 

提示:檢查一些所謂ordinal,它的枚舉常量的序數(它在枚舉聲明,其中初始常量的零序位置)。

+0

謝謝,但是我不希望有一個與HashMap相關的開銷來處理這種簡單的任務。 – nadro

+0

嗯,有'EnumMap',正好避免了「開銷相關的HashMap」,當密鑰類型是'enum'類型。當然,由於'value'不是'final',所以靜態初始化器可以覆蓋零值而不是填充映射,'toInt'可以像以前一樣工作...... – Holger

0

在Android中,最好的做法是避免使用枚舉的主要原因是基於Android文檔防優化性能,:

枚舉往往需要比兩倍的內存多爲靜態 常量。你應該嚴格避免在Android上使用枚舉。

在另一側機器人目的解決方案的類型DEF註釋:

的@IntDef註解讓你基本上創建一個「的typedef」,其中 創建另一個註釋其表示有效的整數 常量你期望的,然後你用這個012deftypedef註釋來裝飾你的API。

下面是一個簡單例子,如何使用它(天的檢查...): https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/

而對於更多會心的功能,你可以閱讀官方文檔: https://developer.android.com/studio/write/annotations.html#enum-annotations