Java - 带静态计数器的枚举



我想在Java中实现像枚举一样C++,所以我想使用静态字段作为计数器。这是我当前的解决方案:

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 代码,以及它是否可以在所有有效的 Java 虚拟机上正常工作,因为 AFAIK 枚举是在静态字段之前初始化的,但是在这种情况下,它看起来像按需初始化具有静态字段的嵌套类可以正常工作(没有嵌套类, 简单的静态字段不起作用)。

此致敬意帕特里克

CounterHolder将始终在初始化之前加载和初始化ETest因此您的代码应该在所有兼容的JVM上按预期工作。您可以在 JLS 中阅读有关类初始化的更多信息(不确定 android 的等效文档是什么,但我希望它们具有非常相似的措辞)。特别:

类或接口类型T将在以下任一情况首次出现之前立即初始化:

  • [...]
  • 使用 T 声明的静态字段,该字段不是常量变量。

因此,最迟在运行ETest的第一个构造函数之前加载和初始化 CounterHolder 类。

但请注意,从风格的角度来看,只写

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

您可以使用枚举中的 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()));
}

输出为:

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

提示:检查称为序数的东西,它是枚举常量的序号(它在枚举声明中的位置,其中初始常量被分配为零序数)。

在 android 中,最佳做法是避免使用 Enum,主要原因是反优化性能,基于 android 文档:

枚举通常需要的内存是静态内存的两倍多 常数。您应该严格避免在Android上使用枚举。

在另一侧 android 目的的解决方案类型定义注释:

@IntDef注释基本上可以让你创建一个"typedef",其中 创建另一个表示有效整数的批注 您期望的常量,然后使用此常量装饰您的 API typedef annotation

.

这是一个示例示例,如何使用它(天数检查器...https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/

有关更多了解的功能,您可以阅读 官方文档 :https://developer.android.com/studio/write/annotations.html#enum-annotations

最新更新