Java枚举可变性用例和可能性?
我不知道我是否是唯一知道这一点的人,但枚举的值不是隐式的最终值,可以修改Java枚举可变性用例和可能性?,java,spring,enums,Java,Spring,Enums,我不知道我是否是唯一知道这一点的人,但枚举的值不是隐式的最终值,可以修改 enum EnumTest { TOTO("TOTO 1"), TATA("TATA 2"), ; private String str; private EnumTest(String str) { this.str = str; } @Override public String toString() { return s
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”)
),但是,除了我自己,我从来没有见过任何人使用final关键字作为枚举变量,这些变量应该是不可变的。这不是问题的重点,只是想知道是否只有我知道这一点
我想知道的是,是否有创建可变枚举的用例 我还想知道我们可以用enum做什么的限制(好的实践与否)。 我还没有测试过它,但也许可以用SpringBean注入enum? 至少我们似乎可以对每个实例(例如@Deprecated可以很好地工作)以及方法进行注释 我想知道的是,是否有创建可变枚举的用例
枚举常量本身不是可变的,它们的字段是可变的 虽然您在这里指出了一个有趣的事实,但就我而言,可变枚举字段没有任何用处。使用这种语言的“功能”(“bug”?)是个坏主意的原因有很多,其中最重要的一个原因是可能会让其他开发人员感到困惑。一个可能的用例是延迟初始化(在首次使用某些字段值时计算它们,如果它们经常不被使用),或者是“正常的”可变单例对象(像登记处之类的)
然而,在大多数情况下,枚举对象应该是不可变的,它们的字段是最终的。为了回应Alex D的回答和评论,我采纳了他的建议,发布了一个可能的用例。让我们以旧的标准枚举对象为例,从中可以计算重力等。假设您想要保持人类的co数量是的,你可以使用EnumMap,但我可以看到一种情况,在这种情况下,可能需要越来越多的可变字段,并且每个值都有一个单独的映射,或者有一个单独的类来保存与enum关联的可变值,这是违反直觉的
正如我在评论中所说,一般来说,我认为枚举通常是不可变的,应该是不可变的,但我觉得说没有用例太强了。我认为没有理由禁止在
enum
s中使用可变字段。可以使用enum
来声明类型的值属于有限(已知)类型之一这并不意味着这些值不能具有随时间变化的属性
一些人要求为这种场景提供用例。一个例子是使用枚举
类型,例如错误类别
,它将错误分类为任意数量的预定义类别之一(例如:DocumentationError
,语义错误
,LayoutError
)
假设那些ErrorCategories
具有属性,例如requireinstantintervision
或shouldldfailbuild
。我可以想象这些属性的值可能会随着时间的推移而改变,或者可以由用户配置
我意识到还有(许多)其他的实现方法(比如上面提到的
EnumMaps
)人们总是会争论样式,但对我来说,使用enum
s本身并没有错。因为enum
s在java中是引用类型,=
的行为保持不变,就好像当初没有可变属性一样。enum实例是enum类的一个公共静态最终字段。因此,如果它是mutable,您可以在另一个线程中修改它的状态。这可能不是您想要的,如果您没有意识到这一点,可能会导致问题。我使用可变枚举来处理在我的控制之外的序列化数值,我希望在使用和中继时保留这些数值
VALUE_A = 1
VALUE_B = 13
VALUE_C = 17
VALUE_UNRECOGNIZED
e、 如果我收到序列化值61怎么办?我不识别它,所以我没有枚举常量,我不处理它,但我不想让它失败:我想保留序列化值并将其转发
也许规范的方法可能是创建一个包含两个字段的新类:不可变枚举和原始值,但是,IMHO,这似乎更麻烦。如果我错了,请纠正我,但枚举是最简单的(更重要的是,可能是最安全的)在Java中,在应用程序的整个生命周期中(如果我们不能使用CDI),实际上都有一个真正的单例,因为使用标准的静态getInstance()方法模式仍然可以生成同一类的多个实例,如果实现得太简单的话 [同样,实现Serializable还可能导致产生不止一个实例,而Enum已经为我们处理了它,没有意外的结果和样板文件。] 此外,文档清楚地表明,枚举类型不仅仅是常量。因此,我想说,每当绝对需要在应用程序中有一个真正的单例时,枚举(甚至是可变的)可能会被视为合理使用
然而,在我看来,这个问题不可避免地倾向于有点固执己见,不能完全公正地回答,因为有些开发人员支持不变性(我并不是说没有充分的理由)但是,在这方面不那么严格的开发人员和基本的文档技能有时可能与代码本身一样重要(是什么阻止我们强调Enum常量的内部状态在javadoc中实际上是可变的?)我理解他的意思。是的,这就是我的意思,但是“常规”用例是创建不可变的枚举,但没有人使用“final”,这是因为很少有带有
public
字段的enum
或公共方法来更改字段IMHO。但我同意应该声明字段final