57

Using reflection on Java classes to access all field, methods, and so on:
Is there a standardized order of these elements (which is specified in some standard)?

Of course, I could check it empirically, but I need to know if it's always the same.

EDIT:
I waited for the question: What I need the order for ;)
Long story short: I have JAXB-annotated classes, and want no represent these classes visually. While the order of XML attributes is neither relevant for the XML standard, nor for JAXB, I want to have a certain order the XML attributes for the visual representation.
For example: start comes after end. This hurts one's intuition.

ivan_ivanovich_ivanoff
  • 19,113
  • 27
  • 81
  • 100
  • I concur with kd304, this has piqued my interest... – Adam Paynter Jul 08 '09 at 12:48
  • 4
    If these are your classes, you can annotate them with some @Order(value=11) annotation and your display sorts the fields according to value. – akarnokd Jul 08 '09 at 12:57
  • @kd304 : I think you should put that last comment as an answer, it could be the solution he's searching for – Valentin Rocher Jul 08 '09 at 15:50
  • @Bishiboosh: Okay, I will compose a small example. – akarnokd Jul 08 '09 at 17:03
  • FWIW, order is important when turning the JAXB-annotated classes into XSDs. Right now, one has to provide the propOrder attribute in a class annotation to guarantee a specific order. Wouldn't it be swell if the XSD order is the declaration order? – Thomas Jung Feb 24 '15 at 03:09

3 Answers3

73

According to the documentation:

getFields()

Returns an array containing Field objects reflecting all the accessible public fields of the class or interface represented by this Class object. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if the class or interface has no accessible public fields, or if it represents an array class, a primitive type, or void.

getMethods()

Returns an array containing Method objects reflecting all the public member methods of the class or interface represented by this Class object, including those declared by the class or interface and those inherited from superclasses and superinterfaces. Array classes return all the (public) member methods inherited from the Object class. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if this Class object represents a class or interface that has no public member methods, or if this Class object represents a primitive type or void.

ManoDestra
  • 6,325
  • 6
  • 26
  • 50
Adam Paynter
  • 46,244
  • 33
  • 149
  • 164
44

A sample for my annotation based idea.

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());
        }
    }

}
akarnokd
  • 69,132
  • 14
  • 157
  • 192
8

Even though getFields() and getMethods() return results in no particular order, you can add the elements in the returned arrays to collections, and provide your own Comparator to sort them however you want.

In this example, I'm just sorting the fields and methods based on the alphabetical order of their names - but you could sort them based on declaring class, modifiers, return types, etc. by providing the required logic in the respective 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()));
    }

}
Nate
  • 16,748
  • 5
  • 45
  • 59