关于枚举:我可以在Java中在运行时添加和删除枚举元素

Can I add and remove elements of enumeration at runtime in Java

在运行时,可以在Java中添加和删除枚举中的元素吗?

例如,我可以从文件中读取枚举的标签和构造函数参数吗?

@Saua,这只是一个是否真的出于兴趣才可以完成的问题。我希望有一种巧妙的方法来改变运行的字节码,也许使用BCEL或者其他什么方法。我也跟进了这个问题,因为我意识到我不完全确定什么时候应该使用枚举。

如果我想在运行时安全地更改内容,我相信正确的答案应该是使用确保唯一性的集合,而不是枚举。


不,枚举应该是完整的静态枚举。

在编译时,您可能希望从某种源文件生成EnUn.java文件。甚至可以创建这样的.class文件。

在某些情况下,您可能需要一组标准值,但允许扩展。通常的方法是让接口使用interface,让标准值使用interface。当然,当你只提到interface时,你就失去了对switch的能力。


在帷幕后面,枚举是带有一个私有构造函数和一组枚举类型的公共静态最终值的pojos(参见这里的示例)。事实上,直到java5,用这种方式构建自己的枚举被认为是最佳实践,而java5引入了enum关键字作为速记。有关详细信息,请参阅Enum的源代码。

因此,使用由构造函数读取或传递给它的公共静态最终常量数组编写自己的"typesafeenum"应该没有问题。

另外,帮自己一个忙,重写equalshashCodetoString,如果可能,创建values方法。

问题是如何使用这种动态枚举…您不能从文件中读取值"pi=3.14"来创建enum MathConstants,然后继续使用MathConstants.PI,无论您想在哪里……


我需要这样做(为了单元测试的目的),我遇到了这个-Enumbuster:http://www.javaspecialists.eu/archive/issue161.html

它允许添加、删除和还原枚举值。

编辑:我刚刚开始使用它,发现Java 1.5需要一些细微的改变,而我现在则坚持:

  • 添加静态助手方法的数组副本(例如,采用以下1.6版本:http://www.docjar.com/html/api/java/util/arrays.java.html)
  • 将Enumbuster.UndoStack更改为Stack
    • 在undo()中,将undostack.poll()更改为undostack.isEmpty()?空:undostack.pop();
  • String ValueSyField需要为我尝试过的Java 1.5枚举"枚举值"。

在我年轻的职业生涯中,我面临着这个问题。

我采用的方法是从外部保存枚举的值和名称,最终目标是能够编写尽可能接近语言枚举的代码。

我希望我的解决方案看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum HatType
{
    BASEBALL,
    BRIMLESS,
    INDIANA_JONES
}

HatType mine = HatType.BASEBALL;

// prints"BASEBALL"
System.out.println(mine.toString());

// prints true
System.out.println(mine.equals(HatType.BASEBALL));

最后我得到了这样的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// in a file somewhere:
// 1 --> BASEBALL
// 2 --> BRIMLESS
// 3 --> INDIANA_JONES

HatDynamicEnum hats = HatEnumRepository.retrieve();

HatEnumValue mine = hats.valueOf("BASEBALL");

// prints"BASEBALL"
System.out.println(mine.toString());

// prints true
System.out.println(mine.equals(hats.valueOf("BASEBALL"));

由于我的要求是必须能够在运行时向枚举添加成员,因此我还实现了该功能:

1
2
3
4
5
6
7
8
9
10
11
12
hats.addEnum("BATTING_PRACTICE");

HatEnumRepository.storeEnum(hats);

hats = HatEnumRepository.retrieve();

HatEnumValue justArrived = hats.valueOf("BATTING_PRACTICE");
// file now reads:
// 1 --> BASEBALL
// 2 --> BRIMLESS
// 3 --> INDIANA_JONES
// 4 --> BATTING_PRACTICE

我把它命名为动态枚举"模式",您可以阅读原始设计及其修订版。

两者的区别在于修订版是在我真正开始摸索OO和DDD之后设计的。第一个是我在写名义上的程序性DDD时设计的,时间压力不小。


您可以尝试将属性分配给您试图创建的枚举,并使用加载的属性文件静态地构造它。大黑客,但它起作用了:)


可以在运行时从源加载Java类。(使用JCI、Beanshell或JavaCompiler)

这将允许您根据需要更改枚举值。

注意:这不会改变任何引用这些枚举的类,因此这在实际中可能不太有用。