Ответ 1
Он должен быть стабильным, а для Oracle JVM - его порядок, который они объявлены, но вы не должны полагаться на это.
Вы должны основывать поиск по имени поля (и, возможно, объявлению класса), а не положению.
Javadoc для Class.getFields()
скажет: "Элементы возвращаемого массива не отсортированы и не находятся в каком-либо конкретном порядке".
Какие-либо намеки на то, как определяется порядок? Возможно ли, что, когда я выполняю этот метод дважды, я получаю поля в другом порядке? Другими словами, стабилен порядок для данного скомпилированного класса или даже между компиляциями одного и того же исходного файла?
Он должен быть стабильным, а для Oracle JVM - его порядок, который они объявлены, но вы не должны полагаться на это.
Вы должны основывать поиск по имени поля (и, возможно, объявлению класса), а не положению.
В моем JVM, по крайней мере,
Class.getFields() возвращает поля в порядке объявления.
Class.getMethods(), с другой стороны, не всегда. Он возвращает их в (я считаю) порядок, который класс загрузчик видит в строках. Поэтому, если два класса имеют одно и то же имя метода, второй загруженный класс возвращает имя общего метода перед другими его методами.
javap подтверждает, что компилятор написал оба поля и методы в порядке объявления.
См. вывод этого примера кода.
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class OrderTest {
public static void main(String[] args) {
// fields are in declaration order
for (Field field : C1.class.getDeclaredFields()) {
System.out.println(field.getName());
}
for (Field field : C2.class.getDeclaredFields()) {
System.out.println(field.getName());
}
// methods, on the other hand, are not necessarily in declaration order.
for (Method method : C1.class.getDeclaredMethods()) {
System.out.println(method.getName());
}
for (Method method : C2.class.getDeclaredMethods()) {
System.out.println(method.getName());
}
}
}
class C1 {
public int foo;
public int bar;
public int getFoo() { return foo; }
public int getBar() { return bar; }
}
class C2 {
public int bar;
public int foo;
public int getBar() { return bar; }
public int getFoo() { return foo; }
}
на моем JVM (1.7.0_45, Windows) это возвращает
foo
bar
bar
foo
getFoo
getBar
getFoo
getBar
Создайте вспомогательный метод, который возвращает отсортированный список, и используйте его, когда вам нужен список полей. Или искать по имени вместо индекса.
Естественный порядок свойств предлагает структуру Ujorm с его объектами с ключом, используя метод readKeys(). Каждый элемент результата имеет аналогичные функции, такие как поле, включая чтение и запись значений с/на объект. Например, см. Следующий код:
public class User extends AbstractUjo implements Serializable {
/** Factory */
private static final KeyFactory<User> f = newFactory(User.class);
/** Keys: */
public static final Key<User, Long> PID = f.newKey();
public static final Key<User, Integer> CODE = f.newKey();
public static final Key<User, String> NAME = f.newKey();
public static final Key<User, Double> CASH = f.newKey();
static {
f.lock();
}
// Setters:
public void setPid(Long pid) {
PID.setValue(this, pid);
}
public void setCode(Integer code) {
CODE.setValue(this, code);
}
public void setName(String name) {
NAME.setValue(this, name);
}
public void setCash(Double cash) {
CASH.setValue(this, cash);
}
// Getters ...
}
Естественный порядок ключей можно повторить:
for (Key key : new User().readKeys()) {
System.out.println("Key: " + key);
}
Дополнительную информацию см. в документации.