web-dev-qa-db-ja.com

Javaリフレクション:クラスフィールドとメソッドの順序は標準化されていますか?

Javaクラスでリフレクションを使用してすべてのフィールド、メソッドなどにアクセスする:
これらの要素の標準化された順序はありますか(これはいくつかの標準で指定されています)?

もちろん、私はcouldを実験的に確認しますが、常に同じかどうかを知る必要があります。

編集:
私は質問を待っていました:注文が必要なもの;)
長い話:私はJAXB注釈付きのクラスを持っているので、これらのクラスを視覚的に表現したくありません。 XML属性の順序はXML標準にもJAXBにも関係ありませんが、視覚的表現のために特定の順序でXML属性を設定したいと考えています。
例:開始は終了の後に来ます。これは直感を傷つけます。

ドキュメント によると:

getFields()

このClassオブジェクトが表すクラスまたはインターフェースのすべてのアクセス可能なパブリックフィールドを反映するFieldオブジェクトを含む配列を返します。 返される配列の要素は並べ替えられておらず、特定の順序にもありません。このメソッドは、クラスまたはインターフェイスに長さが0の配列を返します。アクセス可能なパブリックフィールド、またはそれが配列クラス、プリミティブ型、またはvoidを表す場合。

getMethods()

クラスまたはインターフェースによって宣言されたものや、スーパークラスおよびスーパーインターフェースから継承されたものを含め、このClassオブジェクトによって表されるクラスまたはインターフェースのすべてのパブリックメンバーメソッドを反映するMethodオブジェクトを含む配列を返します。配列クラスは、Objectクラスから継承されたすべての(パブリック)メンバーメソッドを返します。 返される配列の要素は並べ替えられておらず、特定の順序にもありません。このClassオブジェクトがクラスを表す場合、このメソッドは長さ0の配列を返しますまたは、パブリックメンバーメソッドを持たないインターフェイス、またはこのClassオブジェクトがプリミティブ型またはvoidを表す場合。

61
Adam Paynter

私の注釈ベースのアイデアのサンプル。

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

}
36
akarnokd

GetFields()とgetMethods()が特定の順序で結果を返さなくても、返された配列の要素をコレクションに追加し、独自のコンパレータを提供して、必要に応じてそれらを並べ替えることができます。

この例では、フィールドとメソッドを名前のアルファベット順に基づいて並べ替えているだけですが、それぞれのコンパレータで必要なロジックを提供することで、クラス、修飾子、戻り値の型などの宣言に基づいて並べ替えることができます。

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

}
8
Nate