Статические блоки и Field.get (null) со статическими не примитивными полями данных - PullRequest
0 голосов
/ 14 ноября 2011

У меня есть следующие классы:

public class A {

    static {
        B.load(A.class);
    }

    public static final C field1 = new C("key1", "value1");

    public static final C field2 = new C("key2", "value2");

    public static void main(String[] args) {
        System.out.println(A.field1);
    }

}

и

public class B {

    public static void load(Class<?> clazz) {
        for (Field field : clazz.getFields()) {
            try {
                System.out.println("B.load -> field is " + field.get(null));
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

}

и

public class C {

    private final String key;

    private final String value;

    public C(String key, String value) {
        super();
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return this.key;
    }

    public String getValue() {
        return this.value;
    }

    @Override
    public String toString() {
        return "C [key=" + this.key + ", value=" + this.value + "]";
    }

}

Когда A выполняется, я получаю:

B.load -> field is null
B.load -> field is null
C [key=key1, value=value1]

Почему field.get (null) возвращает нулевое значение при его выполнении?Я не получаю исключения, и кажется, что это поведение не объясняется Javadoc.

Ответы [ 2 ]

1 голос
/ 14 ноября 2011

В вашем классе A вы должны объявить статические поля перед вызовом вашей статической функции.

public static final C field1 = new C("key1", "value1");

public static final C field2 = new C("key2", "value2");

static {
    B.load(A.class);
}

В руководстве Java это объясняется:

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

1 голос
/ 14 ноября 2011

Я полагаю, что все статические члены будут выполнены (для статических блоков) и инициализированы (для статических полей) в порядке объявления. Попробуйте поместить статический блок класса A в конец класса или хотя бы после статических полей. Дай мне знать, если это имеет значение.

РЕДАКТИРОВАТЬ: информация о поведении для примитивов и строк ...

Когда у вас есть последнее статическое поле, которое является примитивом или литералом String (или выражением, которое может быть статически оценено, что приводит к одному из них), оно считается константой времени компиляции. По сути, установка такого значения не требует «вычислений», таких как вызов конструктора или оценка других полей, которые, возможно, еще не были инициализированы. Хотя строки не являются примитивами, им при компиляции предоставляется специальная обработка, чтобы сделать строковые литералы в коде возможными.

Это означает, что такие поля можно назначать, как только класс загружен и готов к инициализации. Хотя я не знаю подробностей спецификации относительно этого, эксперименты с отражением показывают, что это то, что должно происходить.

Следующие разделы спецификации языка Java имеют отношение к пониманию этого поведения:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...