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