枚举设置为null后,为什么会保留此值

时间:2016-06-30 20:33:18

标签: java enums

尝试创建标记枚举以使其包含多个状态时。我注意到一些奇怪的事情。更改枚举的内部值时,其名称不会更改。奇怪的是,这个内部值(在我的情况下是一个int)保持最高值,直到我明确地将值设置为0。

这是我用来进一步测试这个

的枚举
public enum flags {
   None(0), flag1(1 << 0);

   private int value;

   private flags(int value) {
       this.value = value;
   }

   public boolean hasFlag(flags flag) {
       return (flag.value & value) == flag.value;
   }

   public void addFlag(flags flag) {
       value |= flag.value;
   }

   public int getValue() {
       return value;
   }

   public void setValue(int value) {
      this.value = value;
   }
}

我已尝试过将这些内容设置为0

    flags flag = flags.None;
    System.out.println(flag + " " + flag.getValue());
    // prints: None 0

    flag.addFlag(flags.flag1);
    System.out.println(flag + " " + flag.getValue());
    // prints: None 1

    flag = flags.None;
    System.out.println(flag + " " + flag.getValue());
    // prints: None 1 even though
    // its been set to flags.None which has a value of 0

    flag = null;
    flag = flags.None;
    System.out.println(flag + " " + flag.getValue());
    // prints: None 1. Even though the enum has been set to null before
    // setting the value to null

    flag = null;
    flag = flags.flag1;
    flag = flags.None;
    System.out.println(flag + " " + flag.getValue());
    // prints: None 1. Even though it is set to
    // another value after being set to null
    // and then set to None

    flag.setValue(0);
    System.out.println(flag + " " + flag.getValue());
    // prints: None 0. As expected

我的问题如下:    为什么价值如此持久,这里发生了什么?

3 个答案:

答案 0 :(得分:5)

我认为你严重误解了Java枚举的目的和功能。根据定义,枚举singletons,意味着枚举的每个定义都是每个运行时构造一次且仅构造一次。换句话说,您不能拥有两个flags.None个实例;

可以 - 但是 - 声明引用您的枚举的多个字段。就像你可能会说flags.None一样,你可以声明一个&#34;标志&#34;变量如int i = 0。这不会创建&#34; None&#34;的新版本,但它是对&#34; None&#34;的引用。枚举。修改&#34;无&#34;的状态(这是一个坏主意恕我直言)将在整个申请过程中全球出现。

另外,你不应该把自己的点缀在你写的枚举中。我建议你看一下EnumSet吗?这将产生更易读的代码,并且是实现您正在尝试完成的内容的有利方式。

答案 1 :(得分:1)

问题是,枚举只有每个值的一个实例(在您的情况下为flags myFlag = flags.NoneNone)。因此编辑这个实例,将永远改变它。如果您向flag1添加标记,则原始None实例会发生变化(与None中的相同),并且会一直保持这种状态,直到您再次更改为止。

答案 2 :(得分:1)

当您声明枚举时,您实际上是在声明一系列静态对象。通过更改静态对象的成员(addFlag调用),您已对其进行了修改,因此所有其他引用都将引用相同的值。

您误解的另一部分是,当您将标志分配给null或其他值时,您不会消除枚举。 Java是通过引用传递的,因此您所做的就是更改标志变量所指的内容。这就是为什么在代码结束时,当setValue为0时,枚举的None成员再次按预期显示0。你可以通过重新分配None和flag1枚举成员的值来解决这个问题。

最后,这真的不是枚举的用法。我不确定你试图使用它,但你可以很容易地使用基于你在这里提供的常规类。当你想要严格的类型检查和明确指示(命名)每个值的含义时,最好使用枚举;例如错误代码枚举。但不应重新分配或修改其中的值。当然显然你可以做到这一点,我只是说它可能会让看到你工作的其他人感到困惑。