我正在尝试以半有效的方式实现某些目标。在我的程序中,我有一个枚举器,代表用于在程序中传递信息的指标。
我有一个类,可以让我将这些指标“组合”成一个对象,这样我就可以创建一个“句子”来为我提供复杂的信息,而不必进行任何复杂的信息解析。它们本质上是位标志,但是由于我使用的是枚举,因此我可以拥有不止64个标志。
问题在于,如果我要大量实例化此容器类的实例,然后去创建一个像这样的数组:
metrics = new boolean[Metrics.values().length];
我想创建一个枚举值数组,以至于经常仅仅要求其大小是浪费的。我想知道是否有可能仅在静态上下文中定义枚举values()的大小,以便它是一个常量值,而不必重新计算:
private static final int METRIC_COUNT = Metrics.values().length;
我可以这样做吗?还是编译器在声明此静态变量之前未定义枚举值?我知道这不是对我的问题的最好解释,但是我不确定该怎么写。
我知道静态变量将在运行时确定(除非分配给它的值是文字值),那么程序是否可以在执行的这一点上请求Metrics枚举的成员?
答案 0 :(得分:10)
EnumSet
将这些指标“组合”成一个对象
本质上是位标志
像您这样的声音需要一个位数组,并针对每个预定义的枚举值的存在/不存在进行翻转。
如果是这样,则无需自己动手。使用EnumSet
或EnumMap
。这些是Set
和Map
接口的特殊实现。这些类由于具有枚举的性质而非常高效,占用的内存很少,执行速度也很快。
以内置的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。
如果您使用Pet
,DOG
和CAT
定义枚举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;
}
请注意,我并没有像其他人在评论中那样专门解决枚举问题。我只是提出一种推迟全局值设置直到需要它的方法。