Вопрос-ответ

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

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

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

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


@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

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

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


  • Добавьте копию массива статических вспомогательных методов (например, возьмите эти версии 1.6: http://www.docjar.com/html/api/java/util/Arrays.java.html)

  • Измените EnumBuster.UndoStack на стек<Memento>

    • В undo() измените UndoStack.poll() на UndoStack.isEmpty() ? null : UndoStack.pop();


  • Поле string VALUES_FIELD должно быть "ENUM $VALUES" для перечислений java 1.5, которые я пробовал до сих пор

Ответ 4

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

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

Я хотел, чтобы мое решение выглядело следующим образом:

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", и вы прочитали об оригинальном дизайне и его исправленной версии.

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

java enums