Объяснение того, как загрузчик классов загружает статические переменные
Хорошо, так что это вопрос новичков в 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;
}
Этот код дает мне исключение инициализации из-за ошибки nullpointer в следующей строке
String [] listCode = new String [LIST_INTEGER.length];
Кажется, что переменная LIST_INTEGER в это время равна нулю.
Может кто-нибудь объяснить, почему? является ли процесс загрузчика классов линейным, другими словами, вызывает ли он метод до полной загрузки всех других переменных?
Ответы
Ответ 1
Да, короче говоря, он линейный.
"То, что на самом деле делает компилятор, это внутренне производить один класс инициализации, которая объединяет все инициализаторы статической переменной и весь статический инициализатор блоков кода в том порядке, в котором они появляются в объявлении класса. Эта выполняется одиночная процедура инициализации автоматически, только один раз, когда класс сначала загружен."
Взято из 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();
Ответ 2
JVM, действительно, инициализирует статические поля в том порядке, в котором они встречаются.
Статические поля класса инициализируются, когда класс впервые встречается JVM. Согласно Java Puzzlers, головоломка 49 (которая идет на ссылку JLS 4.12.5), статические поля сначала устанавливаются в значения по умолчанию. Переменные объекта установлены на null
, int
установлены на 0 и т.д. После этого их инициализаторы выполняются в порядке появления.
Итак, в вашем примере LIST_CODE
и LIST_INTEGER
сначала установлены на null
. Затем LIST_CODE
инициализируется вызовом gerarListCode()
. LIST_INTEGER
по-прежнему null
, когда этот метод выполняется. Только после этого LIST_INTEGER
инициализируется буквенным значением, которое вы укажете в вашем примере.