为什么在枚举构造函数中创建的所有枚举值的数组中的最后一个枚举为null?

时间:2017-09-12 17:38:44

标签: java enums constructor initialization

我知道为了正确地迭代枚举,你应该做

for (Days day : Days.values() {}

我在工作日和周末的enum Days中创建了static数组。我通过在构造函数中执行= new Days[] {SAT, SUN}来使用适当的Days值填充它们。当我迭代它们时,它们按预期工作。

然而,当我为所有Days值创建自己的静态数组时,我迷失了 - 以与以前完全相同的方式添加它们。迭代过这个数组后,我的最后一个元素就是null。无论Days enum中有多少元素 - 我开始添加更多虚构的日子来测试 - 结果是一样的。 “解决方案”是将其final。但是,我想了解我做错了什么。

这告诉我在枚举构造函数中初始化数组是坏的。我的工作日/周末阵列会遭遇类似的事情吗?这实际上是一个大禁忌吗?在枚举构造函数中不应该做的其他事情是什么?或者更准确地说它应该用于什么?除了做这样的事情

enum Days {
  MON("Monday");

  String fullname;

  private Days(String n) {fullname = n};
}

有人能指出任何可以解释这个问题的文档吗?我可能缺少一些关于java枚举和/或它们的构造函数的队长明显的信息。

在寻找答案的过程中,我发现static {} - 在枚举中这样的静态数组的初始化方面,这是不错的做法?还有其他选择吗?

编辑:因为请求了确切的代码。

public enum Days {
  MON, TUE, WED, THU, FRI, SAT, SUN;

  public static Days[] weekdays;
  public static Days[] weekend;
  public static Days[] all;

  Days() {
    weekdays = new Days[] {MON, TUE, WED, THU, FRI};
    weekend = new Days[] {SAT, SUN};
    all = new Days[] {MON, TUE, WED, THU, FRI, SAT, SUN};
  }
}

String s = ""
for (Days d : Days.all) {
  s += d.toString(); //d is null once it reaches the last item 
}

2 个答案:

答案 0 :(得分:4)

尝试:

public enum Days {
    MON, TUE, WED, THU, FRI, SAT, SUN;

    public static Days[] weekdays = {MON, TUE, WED, THU, FRI};
    public static Days[] weekend = {SAT, SUN};
    public static Days[] all = {MON, TUE, WED, THU, FRI, SAT, SUN};
}

您的代码没有在我的Eclipse IDE中编译。你的代码试图做的是:

  • 定义包含7个实例MON, TUE, WED, THU, FRI, SAT, SUN的枚举(这是第一行)。
  • 当创建任何Days实例时,您将使用特定内容填充三个静态数组(这是构造函数的作用) - 这就是问题所在!在进行实例化时,例如第一个枚举实例(即成为MON),其他实例甚至没有开始生命周期,甚至MON尚未准备好(并且尚未以该名称提供) 。所以数组得到一些未定义/空的内容。
  • 由于您的枚举包含7个值,因此每次有一个实例可用时,您将执行7次数组初始化。最后一个实例是SUN的实例。然后其他6个实例准备好了,第七次覆盖你的数组。这次只缺少SUN,这就是为什么你把最后一个条目仍然为空的原因。

所以,不要在这个enum本身的构造函数中引用枚举值。

顺便说一下,你使用的是什么编译器没有标记编译时错误?

答案 1 :(得分:0)

从我所看到的,你被JLS 8.9.2烧伤了。

  

从构造函数,实例初始化程序块或该类型的实例变量初始化程序表达式引用不是常量变量(第4.12.4节)的枚举类型的静态字段是编译时错误。

由于枚举值为themselves static,因此您的代码违规。

虽然它可能看起来效率低下,但可以做的是将你的getter设置为缓存周末枚举一次的信息,以便稍后再参考。

public Days[] getWeekend() {
    if(null == weekend) {
        weekend = new Days[]{MON, TUE};
    }
    return weekend;
}

我将处理并发问题的问题留作读者的练习。