Я могу добавлять и удалять элементы перечисления во время выполнения в Java


можно добавлять и удалять элементы из перечисления в Java во время выполнения?

например, могу ли я прочитать в метках и аргументах конструктора перечисления из файла?


@saua, это просто вопрос о том, можно ли это сделать из интереса на самом деле. Я надеялся, что будет какой-то аккуратный способ изменить запущенный байт-код, возможно, используя BCEL или что-то. Я также следил за этим вопросом, потому что я понял, что не был полностью уверен когда перечисление должно быть использовано.

Я довольно убежден, что правильным ответом было бы использовать коллекцию, которая обеспечивала бы уникальность вместо перечисления, если я хочу иметь возможность безопасно изменять содержимое во время выполнения.

6 51

6 ответов:

нет, перечисления должны быть полным статическим перечислением.

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

в некоторых случаях может потребоваться набор стандартных значений, но разрешить расширение. Обычный способ сделать это-иметь interface для интерфейса и enum что реализует interface для стандартных значений. Конечно, вы теряете способность switch когда у вас есть только ссылка на interface.

за занавесом перечисления являются POJOs с частным конструктором и кучей публичных статических конечных значений типа перечисления (см. здесь для примера). В самом деле, до тех пор, пока с java5, это считалось наилучшей практики, чтобы построить свой собственный перечисления таким образом, и с java5 представил enum ключевое слово в стенографии. Смотрите источник для Перечисление чтобы узнать больше.

поэтому не должно быть никаких проблем, чтобы написать свой собственный "TypeSafeEnum" с публичным статическим финалом массив констант, которые считываются конструктором или передаются ему.

кроме того, сделайте себе одолжение и переопределить equals,hashCode и toString и если возможно создать values метод

вопрос в том, как использовать такое динамическое перечисление... вы не можете прочитать значение "PI=3.14" из файла для создания enum MathConstants а затем идти вперед и использовать MathConstants.PI везде, где вы хотите...

Мне нужно было сделать что-то вроде этого (для целей модульного тестирования), и я наткнулся на это-EnumBuster: http://www.javaspecialists.eu/archive/Issue161.html

позволяет добавлять, удалять и восстанавливать значения перечислений.

Edit: Я только начал использовать это, и обнаружил, что есть некоторые небольшие изменения, необходимые для java 1.5, которые я в настоящее время застрял с:

  • добавить массив copyOf статические вспомогательные методы (например, возьмите эти версии 1.6:http://www.docjar.com/html/api/java/util/Arrays.java.html)
  • Изменить EnumBuster.undoStack в стек<Memento>
    • в undo () измените undoStack.опрос () для отмены стека.isEmpty ()? null: undoStack.pop ();
  • строка VALUES_FIELD должна быть "ENUM$VALUES" для перечислений java 1.5, которые я пробовал до сих пор

я столкнулся с этой проблемой на формирующий проект моей молодой карьеры.

подход, который я принял, состоял в том, чтобы сохранить значения и имена перечисления извне, а конечной целью было написать код, который выглядел как можно ближе к перечислению языка.

Я хотел, чтобы мое решение выглядело так:

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

я назвал его динамическим перечислением "pattern", и вы читали о оригинальный дизайн и ее пересмотренное издание.

разница между ними заключается в том, что пересмотренное издание было разработано после того, как я действительно начал grok OO и DDD. Первый, который я разработал, когда я все еще писал номинально процедурный DDD, под давлением времени нет меньше.

вы можете загрузить класс Java из исходного кода во время выполнения. (Используя JCI, BeanShell или JavaCompiler)

Это позволит вам изменить значения перечисления, как вы хотите.

Примечание: это не изменит никаких классов, которые ссылаются на эти перечисления, поэтому это может быть не очень полезно в реальности.

вы можете попытаться присвоить свойства перечислению, которое вы пытаетесь создать, и статически построить его с помощью загруженного файла свойств. Большой хак, но он работает :)