13

我不知道我是否是唯一知道这一点的人,但枚举的值并不是隐含的最终值,可以修改。

  enum EnumTest {
    TOTO("TOTO 1"),
    TATA("TATA 2"),
    ;

    private String str;

    private EnumTest(String str) {
      this.str = str;
    }

    @Override
    public String toString() {
      return str;
    }
  }

  public static void main(String[] args) {
    System.out.println(EnumTest.TATA);
    EnumTest.TATA.str = "newVal";
    System.out.println(EnumTest.TATA);
  }

TATA 2
newVal

TOTO("TOTO 1")这些值通常在创建实例时初始化(这不是问题的重点,只是想知道我是否是唯一一个知道这一点的人。


我想知道的是是否有任何用例来创建可变枚举?

而且我还想知道我们可以用枚举做些什么的限制(好的做法与否)。我还没有测试过,但也许可以用 Spring bean 注入枚举?至少看起来我们可以注释每个实例(例如@Deprecated 可以很好地工作)以及方法。

4

8 回答 8

11

一个可能的用例是延迟初始化(在第一次使用时计算一些字段值,如果它们经常根本不使用),或者是“正常”的可变单例对象(如注册表等)。

但是,在大多数情况下,枚举对象应该是不可变的,并且它们的字段是最终的。

于 2012-10-22T18:50:37.120 回答
9

虽然您在这里指出了一个有趣的事实,但就我而言,可变枚举字段没有用例。使用这种语言的“特性”(“bug”?)是一个坏主意的原因有很多,其中最重要的是可能会使其他开发人员感到困惑。

于 2012-10-22T16:50:23.247 回答
3

作为对 Alex D 的回答和评论的回应,我接受了他发布一个可能的用例的建议。让我们以可以计算重力等的行星的旧标准枚举示例为例。想象一下,你想保持每个星球上人类殖民地的数量。是的,您可以使用 EnumMap,但我可以看到可能需要越来越多的可变字段的情况,并且为每个值使用单独的映射或单独的类来保存与枚举关联的可变值将是违反直觉的。

正如我在评论中所说,总的来说,我认为枚举通常是并且应该是不可变的,但我觉得说没有用例太强了。

于 2012-10-23T11:40:09.710 回答
2

我认为没有理由禁止在enums 中使用可变字段。一个人使用 anenum来声明该类型的值属于有限(和已知)的一组可能性中的一个。这并不意味着这些值不能具有随时间演变的属性。

有些人要求提供这种场景的用例。一个示例是使用enum诸如 之类的类型ErrorCategory,它将错误分类为任意数量的预定义类别之一(例如:DocumentationErrorSemanticErrorLayoutError...)。

假设它们ErrorCategories具有诸如requiresInstantInterventionor之类的属性shouldFailBuild。我可以想象这些属性的值可能会随着时间而改变,或者它们可以是用户可配置的。

我意识到有(许多)其他方式来实现这一点(例如EnumMaps上面确实提到的),人们总是可以争论风格,但对我来说,这样使用enums 本身并没有错。由于enums 是 java 中的引用类型,因此 s 的行为==保持不变,就好像一开始就没有可变属性一样。

于 2013-05-16T16:34:59.997 回答
1

枚举实例是枚举类的公共静态最终字段。所以如果它是可变的,你可以在另一个线程中修改它的状态。这可能不是您想要的,如果您没有意识到这一点,可能会导致问题。

于 2015-10-27T07:18:04.907 回答
1

如果我错了,请纠正我,但 Enum 是 Java 中最简单(更重要的是也许是最安全)的方式,可以在应用程序的整个生命周期中实际拥有一个真正的单例(如果我们不能使用 CDI),就像使用标准静态 getInstance () 方法模式如果过于天真地实现,仍然可能产生同一个类的多个实例。

[同样,实现 Serializable 也可能导致产生不止一个实例,而 Enum 已经为我们处理好了它,没有意外的结果和样板。]

此外,文档清楚地表明 Enum 类型不仅仅是常量。所以我想说,只要绝对有必要在应用程序中有一个真正的单例,一个枚举(甚至是可变的)可能被认为是合理的使用。

但是,在我看来,这个问题不可避免地倾向于有点固执己见,并且不能完全公正地回答,因为有些开发人员支持不变性(我并不是说没有充分的理由),但也有开发人员谁在这方面没有那么严格,基本的文档技能有时可能与代码本身一样重要(是什么阻止我们强调枚举常量的内部状态实际上在 javadoc 中是可变的这一事实?)。

于 2018-08-07T21:20:25.600 回答
0

我使用可变枚举来处理我控制之外的序列化数值,我想在使用和中继时保留这些数值。例如

VALUE_A = 1
VALUE_B = 13
VALUE_C = 17
VALUE_UNRECOGNIZED

例如,如果我收到 61 的序列化值怎么办?我不认识它,所以我没有枚举常量,我不会以其他方式处理它,但我不想让它失败:我想保留序列化值并将其转发。

也许规范的方法可能是创建一个具有两个字段的新类:一个不可变的枚举和原始值,但是,恕我直言,这似乎更麻烦。

于 2018-08-07T19:22:32.807 回答
-3

我想知道的是是否有任何用例来创建可变枚举?

枚举常量本身不是可变的,它们的字段是可变的。

于 2012-10-22T16:45:59.580 回答