Отражение Java: упорядочен ли порядок полей и методов класса?

Использование отражения на Java-классах для доступа ко всему полю, методам и т.д.:
Существует ли стандартизованный порядок этих элементов (который указан в некотором стандарте)?

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

EDIT:
Я ждал вопроса: что мне нужно для заказа;)
Короче говоря: у меня есть JAXB-аннотированные классы, и я не хочу представляют эти классы визуально. Хотя порядок атрибутов XML не имеет отношения к XML стандарт, ни для JAXB, я хочу иметь определенный порядок атрибутов XML для визуальное представление.
Например: начало начинается после завершения. Это вредит одной интуиции.

Ответ 1

Согласно документации:

getFields()

Возвращает массив, содержащий объекты Field, отражающие все доступные общедоступные поля класса или интерфейса, представленные этим объектом класса. Элементы возвращаемого массива не сортируются и не находятся в каком-либо определенном порядке. Этот метод возвращает массив длины 0, если класс или интерфейс не имеет доступных общедоступных полей или если он представляет класс массива, примитивный тип или пустота.

getMethods()

Возвращает массив, содержащий объекты метода, отражающие все общедоступные методы класса или интерфейса, представленные этим объектом класса, включая те, которые объявлены классом или интерфейсом, и те, которые унаследованы от суперклассов и суперинтерфейсов. Классы массива возвращают все (public) методы-члены, унаследованные от класса Object. Элементы возвращаемого массива не сортируются и не находятся в каком-либо определенном порядке. Этот метод возвращает массив длины 0, если этот объект класса представляет класс или интерфейс, который не имеет методов открытых членов, или если этот объект класса представляет собой примитивный тип или пустоту.

Ответ 2

Пример моей идеи, основанной на аннотациях.

public class FiledOrder {
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Order {
        int value();
    }
    public class SomeClass {
        @Order(value=2)
        public int field1;
        @Order(value=1)
        public int field2;
        // no annotation
        public int field3;
        @Order(value=1)
        public void start() { }
        @Order(value=2)
        public void end() { }
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        Field[] fields = SomeClass.class.getFields();
        Arrays.sort(fields, new Comparator<Field>() {
            @Override
            public int compare(Field o1, Field o2) {
                Order or1 = o1.getAnnotation(Order.class);
                Order or2 = o2.getAnnotation(Order.class);
                // nulls last
                if (or1 != null && or2 != null) {
                    return or1.value() - or2.value();
                } else
                if (or1 != null && or2 == null) {
                    return -1;
                } else
                if (or1 == null && or2 != null) {
                    return 1;
                }
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (Field f : fields) {
            System.out.println(f.getName());
        }
        Method[] methods = SomeClass.class.getMethods();
        Arrays.sort(methods, new Comparator<Method>() {
            @Override
            public int compare(Method o1, Method o2) {
                Order or1 = o1.getAnnotation(Order.class);
                Order or2 = o2.getAnnotation(Order.class);
                // nulls last
                if (or1 != null && or2 != null) {
                    return or1.value() - or2.value();
                } else
                if (or1 != null && or2 == null) {
                    return -1;
                } else
                if (or1 == null && or2 != null) {
                    return 1;
                }
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (Method m : methods) {
            System.out.println(m.getName());
        }
    }

}

Ответ 3

Несмотря на то, что getFields() и getMethods() возвращают результаты без определенного порядка, вы можете добавить элементы в возвращаемые массивы в коллекции и предоставить свой собственный Comparator для их сортировки, но вы хотите.

В этом примере я просто сортирую поля и методы, основанные на алфавитном порядке их имен, но вы можете сортировать их на основе объявления классов, модификаторов, возвращаемых типов и т.д., предоставляя требуемую логику в соответствующем Компаратор.

public void PrintClassData(Class c) {
    Field[] fieldArray = c.getFields();
    Method[] methodArray = c.getMethods();
    SortedSet<Field> fields = new TreeSet<Field>(new FieldComparator());
    fields.addAll(Arrays.asList(fieldArray));
    SortedSet<Method> methods = new TreeSet<Method>(new MethodComparator());
    methods.addAll(Arrays.asList(methodArray));

    StringBuffer b = new StringBuffer("All About ");
    b.append(c.getName());
    b.append("\nFields:\n");
    for(Field f : fields) {
        b.append("\t");
        b.append(Modifier.toString(f.getModifiers()));
        b.append(" ");
        b.append(f.getType());
        b.append(" ");
        b.append(f.getName());
        b.append("\n");
    }
    b.append("\nMethods:\n");
    for (Method m : methods) {
        b.append("\t");
        b.append(Modifier.toString(m.getModifiers()));
        b.append(" ");
        b.append(m.getReturnType());
        b.append(" ");
        b.append(m.getName());
        b.append("( ");
        for (Class param : m.getParameterTypes()) {
            b.append(param.getName());
            b.append(", ");
        }
        b.deleteCharAt(b.lastIndexOf(","));
        b.append(")\n");
    }
    System.out.println(b.toString());
}

private static class FieldComparator implements Comparator<Field> {

    public int compare(Field f1, Field f2) {
        return (f1.getName().compareTo(f2.getName()));
    }   
}

private static class MethodComparator implements Comparator<Method> {

    public int compare(Method m1, Method m2) {
        return (m1.getName().compareTo(m2.getName()));
    }

}