На уровне байт-кода как Java Class.getEnumConstants () узнает, какие классы являются enum-классами? - PullRequest
2 голосов
/ 28 октября 2019

API отражения Java содержит метод Class.getEnumConstants(), который позволяет определить, является ли класс enum классом (он возвращает null, если не считает, что класс enum)и каковы его константы.

Я работаю над программой, которая генерирует байт-код JVM напрямую, и пытаюсь сгенерировать класс enum. Поэтому мне нужно знать, как Java распознает перечислимые классы по их байт-коду, чтобы getEnumConstants работал правильно. Очевидно, что класс должен расширяться Enum, но этого явно недостаточно для этого (например, байт-код, соответствующий public class Example extends Enum<Example> {}, не будет распознаваться как enum);Какие еще функции должен иметь байт-код JVM для класса, чтобы API отражения Java распознал его как Java enum и смог определить его константы перечисления?

1 Ответ

4 голосов
/ 28 октября 2019

Чтобы скомпилировать тип enum, необходимо пометить класс флагом ACC_ENUM в флагах доступа к классу.

Далее, для каждой константы,вам необходимо создать соответствующее поле public static final, которое также помечено ACC_ENUM в флагах доступа к полю.

Затем необходим инициализатор класса (метод no-arg void с именем <clinit>), который создает экземпляры и присваивает их полям.

Но этого недостаточно. Запомните спецификацию языка , которая определяет существование двух неявно объявленных методов

  /**
  * Returns an array containing the constants of this enum 
  * type, in the order they're declared.  This method may be
  * used to iterate over the constants as follows:
  *
  *    for(E c : E.values())
  *        System.out.println(c);
  *
  * @return an array containing the constants of this enum 
  * type, in the order they're declared
  */
  public static E[] values();

  /**
  * Returns the enum constant of this type with the specified
  * name.
  * The string must match exactly an identifier used to declare
  * an enum constant in this type.  (Extraneous whitespace 
  * characters are not permitted.)
  * 
  * @return the enum constant with the specified name
  * @throws IllegalArgumentException if this enum type has no
  * constant with the specified name
  */
  public static E valueOf(String name);

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


Спецификация не описывает, как Reflection будет собирать свою информацию. Он может перебирать отмеченные поля и читать их, собирать массив или просто вызывать метод values() определенного типа. Таким образом, вы не можете опустить ни один из этих артефактов и не можете реализовать метод values(), просто делегировав Class.getEnumConstants().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...