Могу ли я добавлять и удалять элементы перечисления во время выполнения в Java
Можно добавлять и удалять элементы из перечисления в Java во время выполнения?
Например, могу ли я прочитать в аргументах label и constructor перечисления из файла?
@saua, это просто вопрос о том, действительно ли это можно сделать из интереса. Я надеялся, что будет какой-то аккуратный способ изменить исполняемый байт-код, возможно, используя BCEL или что-то в этом роде. Я также рассмотрел этот вопрос, потому что понял, что я не совсем уверен, когда нужно использовать перечисление.
Я уверен, что правильным ответом будет использование коллекции, которая обеспечила бы уникальность вместо перечисления, если я хочу иметь возможность безопасно изменять содержимое во время выполнения.
Ответы
Ответ 1
Нет, перечисления должны быть полным статическим перечислением.
Во время компиляции вам может потребоваться сгенерировать ваш файл enum.java из другого исходного файла. Вы даже можете создать такой файл .class, как это.
В некоторых случаях вам может потребоваться набор стандартных значений, но разрешить расширение. Обычный способ сделать это - interface
для интерфейса и enum
, который реализует это interface
для стандартных значений. Конечно, вы теряете возможность switch
, когда у вас есть только ссылка на interface
.
Ответ 2
За занавеской перечисления представляют собой POJO с частным конструктором и кучей публичных статических конечных значений типа перечисления (см. здесь для пример). Фактически, вплоть до Java5, было сочтено, что лучше всего создать собственное перечисление таким образом, а Java5 представило ключевое слово enum
в качестве сокращенного. Подробнее см. Источник Enum <T> .
Поэтому не должно возникнуть проблемы с написанием собственного "TypeSafeEnum" с открытым статическим окончательным массивом констант, которые считываются конструктором или передаются ему.
Также сделайте себе одолжение и переопределите equals
, hashCode
и toString
и, если возможно, создайте метод values
Вопрос заключается в том, как использовать такое динамическое перечисление... вы не можете прочитать значение "PI = 3.14" из файла для создания enum MathConstants
, а затем продолжить и использовать MathConstants.PI
, где хотите..
Ответ 3
Мне нужно было сделать что-то подобное (для целей тестирования), и я наткнулся на это - EnumBuster:
http://www.javaspecialists.eu/archive/Issue161.html
Он позволяет добавлять, удалять и восстанавливать значения перечислений.
Изменить: я только начал использовать это и обнаружил, что для java 1.5 есть небольшие изменения, которые я сейчас застрял:
- Добавить массив copyOf статических вспомогательных методов (например, взять эти версии 1.6: http://www.docjar.com/html/api/java/util/Arrays.java.html)
- Измените EnumBuster.undoStack на стек
<Memento>
- В undo() измените значение undoStack.poll() на undoStack.isEmpty()? null: undoStack.pop();
- Строка VALUES_FIELD должна быть "ENUM $VALUES" для перечислений java 1.5, которые я пробовал до сих пор.
Ответ 4
Я столкнулся с этой проблемой на формирующем проекте моей молодой карьеры.
Подход, который я принял, состоял в том, чтобы сохранить значения и имена перечисления извне, и конечной целью было уметь писать код, который был как можно ближе к языку enum.
Я хотел, чтобы мое решение выглядело так:
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));
И у меня получилось что-то вроде этого:
// 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"));
Поскольку мои требования заключались в том, что во время выполнения было необходимо добавить участников в перечисление, я также реализовал эту функциональность:
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
Я назвал его шаблоном Dynamic Enumeration, и вы прочитали о исходном проекте и его пересмотренное издание.
Разница между двумя заключается в том, что пересмотренное издание было разработано после того, как я действительно начал проверять OO и DDD. Первый, который я разработал, когда я все еще писал номинально процедурный DDD, под давлением времени не менее.
Ответ 5
Вы можете загрузить Java-класс из источника во время выполнения. (Использование JCI, BeanShell или JavaCompiler)
Это позволит вам изменить значения Enum, как вы пожелаете.
Примечание: это не изменило бы классы, которые ссылались на эти перечисления, поэтому это может быть не очень полезно в действительности.
Ответ 6
Вы можете попытаться присвоить свойства ENUM, который вы пытаетесь создать, и статически конструировать с помощью загруженного файла свойств. Большой взлом, но он работает:)