Определите Enum во время выполнения с помощью ByteBuddy

У меня есть проект, в котором перечисление используется в качестве параметра для класса, подпись которого выглядит следующим образом:

 public class MyClass<E extends Enum<E>> extends ExtendedClass

Дело в том, что я не хочу определять перечисление и снова выполнять одно и то же программирование для каждого нового перечисления.

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

редактировать:

Чтобы быть более конкретным, что у меня есть в моем коде:

private enum MyEnum{
    FOO, BAR;
}

MyClass<MyEnum> obs = new MyClass<MyEnum>() 

Это не работает, когда я использую Enum, сгенерированный ByteBuddy; В данном случае он не считается типом (ошибка компиляции).

Есть ли какой-то трюк или это то, что можно сделать во время выполнения?


person CiCi    schedule 17.08.2016    source источник
comment
Я не знал о ByteBuddy, но, глядя на него, у меня много проблем, и я не вижу особой пользы. Вам действительно нужно создавать так много перечислений?   -  person Ray O'Kalahjan    schedule 17.08.2016
comment
Byte Buddy создает типы во время выполнения. Вы не можете компилировать такие типы. Вы по-прежнему можете использовать Byte Buddy для создания типов перед компиляцией и компиляции с ними. Для этого вам нужно будет расширить свою сборку.   -  person Rafael Winterhalter    schedule 18.08.2016
comment
Добро пожаловать в Stack Overflow! Не могли бы вы дать лучшее название и более подробную информацию в содержании с вашими усилиями по решению проблемы?   -  person Enamul Hassan    schedule 20.08.2016


Ответы (3)


Типы Enum скомпилированы в класс со статическими полями, поэтому

enum MyEnum {
  FOO
}

компилируется в

class MyEnum extends java.lang.Enum<MyEnum> {
  public static final Sample FOO;
  // synthetic
  private static final Sample[] $VALUES;

  static {
    FOO = new MyEnum("FOO", 0);
    $VALUES = new MyEnum[] {FOO};
  }

  private MyEnum(String name, int ordinal) {
    super(name, ordinal);
  }

  // and other helpers
  public static MyEnum[] values() { /* $VALUES */ }
  public static MyEnum valueOf(String name) { /* $VALUES lookup */ }
}

(поэтому enum не может расширять другой класс, только реализовывать интерфейсы). Поэтому вам нужно создать такой класс для эмуляции перечисления.

person vsminkov    schedule 17.08.2016

Вы можете легко создавать перечисления с помощью Byte Buddy:

Class<? extends Enum<?>> type = new ByteBuddy()
  .makeEnumeration("FOO", "BAR")
  // define methods/fields if required.
  .make()
  .load(MyClass.class.getClassLoader())
  .getLoaded();

Это дает вам тип перечисления. Вы можете прочитать константы:

Enum<?> foo = Enum.valueOf(type, "FOO");
Enum<?> bar = Enum.valueOf(type, "BAR");

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

person Rafael Winterhalter    schedule 17.08.2016
comment
Спасибо .. на самом деле это то, что я сделал .. Я отредактировал вопрос, чтобы он был более конкретным, может быть, вы меня лучше поймете .. - person CiCi; 18.08.2016

Вы можете получить Enumeration во время выполнения из любого заданного Collection:

java.util.Collections.enumeration(set)

См. этот ответ SO.

person Markus Mitterauer    schedule 17.08.2016
comment
Enumeration — это не Enum, а тип коллекции. - person Pr0methean; 19.07.2019