Java Reflection: получение полей и методов в порядке объявления

Есть ли способ получить классы, объявленные поля (и методы) в порядке объявления с использованием отражения? Согласно документации, упорядочение методов и полей, возвращаемых getFields(), getDeclaredFields() и т.д., undefined.

Указание чего-то типа индекса возможно с помощью аннотации, как предложено в Отражение Java: упорядочен ли порядок полей и методов класса?

Есть ли лучшие варианты, то есть не нужно указывать индекс вручную?

Теперь, прежде чем вы спросите, для чего мне это нужно: у нас есть метод, который принимает довольно большую структуру данных в качестве входных данных и выполняет длительный расчет на нем. Чтобы создать модульные тесты, мы создали метод, который принимает входной объект и выходной экземпляр и создает исходный код Java (настройку ввода, вызов метода расчета и утверждение правильных результатов впоследствии) в качестве вывода. Этот код намного читаем, когда поля записываются в порядке объявления.

Ответ 1

С помощью jdk 6 отраженные поля записываются в порядке их объявления. В начале jdk это было не так. По-видимому, достаточно людей.

Хотя я не гарантирован javadoc, я все равно принимаю этот порядок как предоставленный, и я полагаю, что заказ будет сохранен и в будущих jdks.

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

Ответ 2

Нет, невозможно отразить. Однако вы можете решить эту проблему с помощью команды ProcessBuilder и javap:

Учитывая Test.java:

public abstract class Test {

    public void method1() {
    }

    public void method2() {
    }

    public static void main(String[] args) {
    }

    public String method3() {
        return "hello";
    }

    abstract void method4();

    final int method5() {
        return 0;
    }
}

Команда javap Test печатает:

...
public Test();
public void method1();
public void method2();
public static void main(java.lang.String[]);
public java.lang.String method3();
abstract void method4();
final int method5();
...

Ответ 3

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

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

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

Ответ 4

У меня это было как изолированная проблема, посмотрите

https://github.com/wmacevoy/kiss/blob/master/src/main/java/kiss/util/Reflect.java

и метод

public static Метод [] getDeclaredMethodsInOrder (класс clazz)

Он получает заказ, глядя на байт-код класса. Если вы просто хотите использовать libray, это будет kiss.util.Reflect.getDeclaredMethodsInOrder(Test.class)

Ответ 5

Вы можете подумать об использовании Javadoc с пользовательским Doclet, но для этого требуется, чтобы источник был доступен.

В API все еще нет гарантии о заказе (methods, fields, но каждый выход javadoc, который я когда-либо видел, имеет их в правильном порядке, поэтому я полагаю, что doclets получают их в порядке объявления.

Ответ 6

Вы не сможете получить информацию из файла класса. Как сказал Адам в ответе на лишний вопрос:

Элементы возвращаемого массива не сортируются и не находятся в определенном порядке.

И "no order" включает в себя "никакой порядок объявления".

Я однажды использовал анализатор исходного файла Java для получения входных данных для генераторов кода. И таким образом у вас будут поля и методы в порядке объявления.