Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么将枚举设置为null后会保留此值_Java_Enums - Fatal编程技术网

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

Java 为什么将枚举设置为null后会保留此值,java,enums,Java,Enums,尝试创建标志枚举以使其包含多个状态时。我注意到一些奇怪的事情。更改枚举的内部值时,其名称不会更改。奇怪的是,这个内部值(在我的例子中是int)一直保持最高值,直到我显式地将该值设置为0 这是我用来进一步测试的枚举 public enum flags { None(0), flag1(1 << 0); private int value; private flags(int value) { this.value = value; }

尝试创建标志枚举以使其包含多个状态时。我注意到一些奇怪的事情。更改枚举的内部值时,其名称不会更改。奇怪的是,这个内部值(在我的例子中是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;
   }
}
我的问题如下:
为什么值如此持久,这里发生了什么?

我认为您严重误解了Java枚举的用途和功能。枚举是按定义构造的,这意味着枚举的每个定义在每个运行时构造一次且仅构造一次。换句话说,您不能有两个
标志<代码>标志。当应用程序运行时,无
永远是一个单一的东西

但是,您可以声明引用枚举的多个字段。就像您可能说的
inti=0
,您可以声明一个“flags”变量,如
flags myFlag=flags.None
。这不会创建“None”的新版本,但它是对“None”枚举的引用。修改“无”状态(这是一个坏主意,IMHO)将在整个应用程序中全局可见


此外,您不应该在编写的枚举中随意翻滚。我可以建议你看一看吗?这将产生可读性更高的代码,并且是实现您试图实现的目标的有利方式。

问题是,枚举每个值只有一个实例(
None
flag1
)。因此,编辑这一实例将永远改变它。如果将标志添加到
None
,则原始的
None
实例将发生更改(与
flags.None
中的相同),并将保持这种方式,直到再次更改它。

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

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


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

你正在修改两个对象的状态。为什么对它们的状态被修改感到惊讶?枚举上的setter应该是一个红旗(双关语),遵循约定并对枚举/类名使用camel case等会很好。@JBNizet我根本不知道枚举是使用静态对象实现的。在一个我不必再担心的项目中,我偶然发现了这一点。
    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