2009-07-08 4 views
42

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

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

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

+1

Зачем вам нужен заказ? – akarnokd

+0

Я согласен с kd304, это вызвало мой интерес ... –

+4

Если это ваши классы, вы можете аннотировать их с помощью аннотации @Order (value = 11), и ваш дисплей сортирует поля в соответствии со значением. – akarnokd

ответ

54

По the documentation:

getFields()

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

getMethods()

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

+1

Спасибо. Печально, что никакого порядка не определено :( –

+1

Нет конкретного заказа и никаких гарантий между различными виртуальными машинами и версиями. – akarnokd

8

Несмотря на то, что 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())); 
    } 

} 
34

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

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

} 
+0

Это работает красиво. Хорошо сделано! – electromaggot

+0

работает для меня. – coffee

+0

Немного поздно, но у меня было это то же самое, и это изящное решение. Очень приятно! – user1452076