Вопрос по classloader, java, static – Объяснение того, как загрузчик классов загружает статические переменные

9

Хорошо, так что это вопрос новичка на Java, но я, кажется, не могу разобраться с этим.

У меня есть следующий код в моем классе

private static final String [] LIST_CODE = gerarListCode();
private static final int [][] LIST_INTEGER = new int [][] {
        {947,947}, {110,103}, 
        {947,958}, {110,120}, 
        {947,954}, {103,107}, 
        {947,967}, {110,99,104}};

 private static String [] gerarListCode()
    {
        String [] listCode = new String [LIST_INTEGER.length];

        for (int i=0 ; i<LIST_INTEGER.length ; i++)
        {
           //do some stuff      
        }

        return listaUnicode;
    }

Этот код дает мне исключение инициализации из-за nullpointerexception в следующей строке

 String [] listCode = new String [LIST_INTEGER.length];

Кажется, переменная LIST_INTEGER в это время пуста.

Может кто-нибудь объяснить, почему? Является ли процесс загрузчика классов линейным, другими словами, вызывает ли он метод перед полной загрузкой всех остальных переменных?

переместить объявление LIST_INTEGER в строку перед LIST_CODE Ron

Ваш Ответ

2   ответа
4

JVM действительно инициализирует статические поля в том порядке, в котором они встречаются.

Статические поля класса инициализируются, когда класс впервые встречается с JVM. В соответствии сJava Puzzlers, головоломка 49 (далее ссылка на JLS 4.12.5), статические поля сначала устанавливаются в значения по умолчанию. Переменные объекта установлены вnull, ints установлены в 0 и т. д. После этого их инициализаторы выполняются в порядке появления.

Итак, в вашем примере,LIST_CODE а такжеLIST_INTEGER сначала установленыnull, Затем,LIST_CODE инициализируется путем вызоваgerarListCode(). LIST_INTEGER все ещеnull когда этот метод выполняется. Только после этогоLIST_INTEGER инициализируется литеральным значением, которое вы даете в своем примере.

Это не относится к загрузчику классов. Это реализуется с помощью javac, создающего статический инициализатор в порядке источника.
Спасибо за улов, Том! Я обновил свой ответ.
11

Да, короче говоря, это линейно.

"What the compiler actually does is to internally produce a single class initialization routine that combines all the static variable initializers and all of the static initializer blocks of code, in the order that they appear in the class declaration. This single initialization procedure is run automatically, one time only, when the class is first loaded."

Взято с Java в двух словах.

http://www.developer.com/java/other/article.php/2238491

Вы должны определить переменные и затем инициализировать их в статическом блоке intitializer в правильном порядке, или вы можете поменять местами операторы следующим образом:

private static final int [][] LIST_INTEGER = new int [][] { {947,947}, {110,103}, 
        {947,958}, {110,120}, 
        {947,954}, {103,107}, 
        {947,967}, {110,99,104}};

private static final String [] LIST_CODE = gerarListCode(); 
Строго говоря, это происходит не тогда, когда класс загружается, а позже, когда он инициализируется.

Похожие вопросы