问题
Let's say I have a file whose format is basic XML, like so:
<?xml version="1.0"?>
<enum-set>
<enum>
<name>SomeEnum</name>
<values>
<value>
<name>SOMEVALUE</name>
<displayText>This is some value</displayText>
</value>
... more values ...
</values>
</enum>
... more enums ...
</enum-set>
and I wanted to turn SomeEnum into something like this at runtime:
public enum SomeEnum implements HasDisplayText {
SOMEVALUE("This is some value"),
... more values ...;
private String displayText;
SomeEnum(String displayText) {
this.displayText = displayText;
}
@Override
public String getDisplayText() {
return displayText;
}
}
... and then pass the newly created enum SomeEnum around my application. How might I achieve something like this? Is it doable?
回答1:
What you're trying to do doesn't make a whole lot of sense. Enums are really only for the benefit of compile time, as they represent a fixed set of constants. At runtime, what would be the meaning of a dynamically generated enum - how would this be different from an plain object? For example:
public class Salutation implements HasDisplayText {
private String displayText;
private Salutation(String displayText) {
this.displayText = displayText;
}
@Override
public String getDisplayText() {
return displayText;
}
public static Collection<Salutation> loadSalutations(String xml) {
//parse, instantiate, and return Salutations
}
}
Your XML could be parsed into newly instantiated Salutation objects, which could be stored in some Collection or otherwise used by your program. Notice in my example, I've restricted the creation of Salutation by giving it a private constructor - in this case the only way to retrieve instances is by calling the factory method which takes your XML. I believe this achieves the behavior you're looking for.
回答2:
Actually it is possible to create enum instances dynamically, but it's a total hack, I wouldn't advise it at all - maybe you're misunderstanding the nature of an enum, it's a compile-time feature of the language, and you're not supposed to add/remove instances from it at runtime.
Anyway, if you're interested in the hack for creating enum instances dynamically, take a look at this article.
回答3:
Dynamic Enums is the answer to your problem:
public abstract class DEnum<E extends DEnum<E>> implements Comparable<E>, Serializable {
This class has a signature similar to the standard Enum class. It has a protected constructor to allow instance creation in concrete Enum classes. For example:
public class YesNo extends DEnum<YesNo> {
public final static YesNo YES = new YesNo();
public final static YesNo NO = new YesNo();
The DEnum class knows the names of the members by introspection:
String name = YesNo.YES.getName();
YesNo yes = YesNo.get(YesNo.class, name);
assert (yes == YesNo.YES);
There is a typed getter that retrieves all the items:
YesNo[] items = yes.getItems();
assert (items.length == 2);
It allows to add members dynamically at run time with (from database or from file):
YesNo maybe = getOrCreateIfNotExists(YesNo.class, "MAYBE");
items = yes.getItems();
assert (items.length == 3);
Which have the same behavior as the static members:
YesNo unknown = YesNo.get(YesNo.class, "MAYBE");
assert (unknown == maybe);
回答4:
Agree with Oscar Lopez. Here is what i did, a sort of hack.
public static enum Setter {
DYNAMIC_ENUM_EXAMPLE {
@Override
public String setGetValue(String yourValue) {
return "prefix " + yourValue + " postfix";
}
};
public abstract String setGetValue(String value);
}
You can get the value like this :
Setter.DYNAMIC_ENUM_EXAMPLE.setGetValue("namaste")
Output :
prefix namaste postfix
来源:https://stackoverflow.com/questions/8467215/generating-enums-dynamically