何时定义枚举值?

时间:2019-02-26 01:18:28

标签: java

我正在尝试以半有效的方式实现某些目标。在我的程序中,我有一个枚举器,代表用于在程序中传递信息的指标。

我有一个类,可以让我将这些指标“组合”成一个对象,这样我就可以创建一个“句子”来为我提供复杂的信息,而不必进行任何复杂的信息解析。它们本质上是位标志,但是由于我使用的是枚举,因此我可以拥有不止64个标志。

问题在于,如果我要大量实例化此容器类的实例,然后去创建一个像这样的数组:

metrics = new boolean[Metrics.values().length];

我想创建一个枚举值数组,以至于经常仅仅要求其大小是浪费的。我想知道是否有可能仅在静态上下文中定义枚举values()的大小,以便它是一个常量值,而不必重新计算:

private static final int METRIC_COUNT = Metrics.values().length;

我可以这样做吗?还是编译器在声明此静态变量之前未定义枚举值?我知道这不是对我的问题的最好解释,但是我不确定该怎么写。

我知道静态变量将在运行时确定(除非分配给它的值是文字值),那么程序是否可以在执行的这一点上请求Metrics枚举的成员?

3 个答案:

答案 0 :(得分:10)

EnumSet

  

将这些指标“组合”成一个对象

     

本质上是位标志

像您这样的声音需要一个位数组,并针对每个预定义的枚举值的存在/不存在进行翻转。

如果是这样,则无需自己动手。使用EnumSetEnumMap。这些是SetMap接口的特殊实现。这些类由于具有枚举的性质而非常高效,占用的内存很少,执行速度也很快。

以内置的DayOfWeek枚举为例。定义七个对象,每个ISO 8601日历的每个星期中的一个。

Set< DayOfWeek > weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ;

使用Set之类的便捷方法,例如contains

boolean isTodayWeekend = weekend.contains( LocalDate.now().getDayOfWeek() ) ;

如果您循环设置集合中的元素,则应保证按枚举中定义的顺序(它们的“自然”顺序)提供它们。因此,从逻辑上讲,EnumSet应该被标记为SortedSet,但是神秘地没有这样标记。不过,您知道顺序。例如,循环EnumSet.allOf( DayOfWeek.class )会首先渲染DayOfWeek.MONDAY,最后渲染DayOfWeek.SUNDAY(按照ISO 8601标准)。

  

何时定义枚举值?

enum的元素是在编译时定义的,并且不能在运行时进行修改(除非您使用反射技巧)。加载类时,每个命名变量都将填充一个实例。参见Section 8.9, Enum Types中的Java Language Specification

如果您使用PetDOGCAT定义枚举BIRD,那么您将知道在运行时始终有三个实例。

您可以通过至少两种方式计算枚举中定义的元素数:

  • 为任何values调用由编译器生成的enum方法,您可以在其中询问结果数组的大小,如您的Question中所示。
    int countDows = DayOfWeek.values().length() ;
  • 在创建所有枚举实例的EnumSet之后调用Set::size
    int countDows = EnumSet.allOf( DayOfWeek.class ).size() ;

答案 1 :(得分:6)

private static final int METRIC_COUNT = Metrics.values().length;
     

我可以这样做吗?

是的,可以。这是缓存长度并确保仅计算一次的正确方法。

  

我知道静态变量将在运行时确定(除非分配给它的值是文字值),那么程序是否可以在执行的这一点上请求Metrics枚举的成员?

是的。根据定义,METRIC_COUNT也在运行时计算。

答案 2 :(得分:-3)

我不知道您是否需要在这种情况下执行此操作,但是我认为我理解一个更普遍的问题,即在执行过程中无法早期计算常量。我遇到了这个问题。我使用的解决方案是这样的……稍后,当您准备使用它并确定已定义Metrics对象时,请计算METRICS_COUNT,但仍然只执行一次:

private static int METRIC_COUNT = -1;

public static int getMetricsCount() {
    if (METRIC_COUNT < 0)
        METRIC_COUNT = Metrics.values().length;
    return METRIC_COUNT;
}

请注意,我并没有像其他人在评论中那样专门解决枚举问题。我只是提出一种推迟全局值设置直到需要它的方法。