Подтвердить что ты не робот

Генерация имен динамически

Скажем, у меня есть файл, формат которого является базовым XML, например:

<?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>

и я хотел превратить SomeEnum во что-то подобное во время выполнения:

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;
    }
}

... и затем передайте вновь созданное enum SomeEnum вокруг моего приложения. Как я могу добиться чего-то подобного? Это выполнимо?

4b9b3361

Ответ 1

То, что вы пытаетесь сделать, не имеет большого смысла. Enums действительно доступны только на время компиляции, поскольку они представляют собой фиксированный набор констант. Во время выполнения, каково будет значение динамически созданного enum - как это будет отличаться от простого объекта? Например:

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
   }
}

Ваш XML может быть проанализирован в недавно созданных объектах Salutation, которые могут быть сохранены в некотором Collection или иным образом использованы вашей программой. Обратите внимание, что в моем примере я ограничил создание Salutation, предоставив ему конструктор private - в этом случае единственный способ получить экземпляры - это вызвать метод factory, который принимает ваш XML. Я считаю, что это позволяет выполнить поведение, которое вы ищете.

Ответ 2

На самом деле можно создавать экземпляры enum динамически, но это полный взлом, я бы вообще не советовал - возможно, вы неправильно понимаете природу enum, это функция времени компиляции языка, и вы не предполагается добавлять/удалять экземпляры из него во время выполнения.

В любом случае, если вас интересует возможность динамического создания экземпляров enum, ознакомьтесь с этой статьей.

Ответ 3

Согласиться с Оскаром Лопесом. Вот что я сделал, своего рода хак.

public static enum Setter {

    DYNAMIC_ENUM_EXAMPLE {

        @Override
        public String setGetValue(String yourValue) {
            return "prefix " + yourValue + " postfix";
        }
    };
    public abstract String setGetValue(String value);
}

Вы можете получить значение, подобное этому:

Setter.DYNAMIC_ENUM_EXAMPLE.setGetValue("namaste")

Выход:

prefix namaste postfix

Ответ 4

Dynamic Enums - это ответ на вашу проблему:

public abstract class DEnum<E extends DEnum<E>> implements Comparable<E>, Serializable {

Этот класс имеет подпись, похожую на стандартный класс Enum. Он имеет защищенный конструктор, позволяющий создавать экземпляры в конкретных классах Enum. Например:

public class YesNo extends DEnum<YesNo> {

    public final static YesNo YES = new YesNo();
    public final static YesNo NO = new YesNo();

Класс DEnum знает имена членов путем интроспекции:

String name = YesNo.YES.getName();
YesNo yes = YesNo.get(YesNo.class, name);
assert (yes == YesNo.YES);

Существует типизированный getter, который извлекает все элементы:

YesNo[] items = yes.getItems();
assert (items.length == 2);

Он позволяет динамически добавлять участников во время выполнения с (из базы данных или из файла):

YesNo maybe = getOrCreateIfNotExists(YesNo.class, "MAYBE");
items = yes.getItems();
assert (items.length == 3);

которые имеют такое же поведение, что и статические члены:

YesNo unknown = YesNo.get(YesNo.class, "MAYBE");
assert (unknown == maybe);