#java #static-initializer
Вопрос:
У меня есть два класса, «Test1» и «Test0», как показано в этом коде.
public class Test1 {
public static void main(String...args) {
System.out.print(Test0.randomName);
}
}
public class Test0 {
public static String randomName = initRandomName();
private static String string0;
static {
string0 = "George";
}
private static String initRandomName() {
return "Mr. " string0;
}
}
Я думал, что там будет напечатан мистер Джордж, но там был напечатан мистер Нуль.
И я не понимаю, что происходит. Пожалуйста, помогите мне. Спасибо.
Комментарии:
1. Перемещение назначения
string0
перед инициализациейrandomName
должно исправить это. Статическая переменная может иметь нулевые значения, иrandomName
доступ кstring0
ней осуществляется еще до того, как ей будет присвоено значение.
Ответ №1:
JLS 12.4.2 подробно описывает процедуру инициализации. В частности:
Затем выполните инициализаторы переменных класса и статические инициализаторы класса или инициализаторы полей интерфейса в текстовом порядке, как если бы они были одним блоком.
Другими словами, вы можете представить, что ваш Test0
класс написан так:
public class Test0 {
public static String randomName;
private static String string0;
static {
randomName = initRandomName();
string0 = "George";
}
private static String initRandomName() {
return "Mr. " string0;
}
}
Поэтому, когда initRandomName()
выполняется, string0
по-прежнему равно нулю.
Вы можете переместить инициализацию randomName
поля в положение после статического инициализатора, например так:
class Test0 {
private static String string0;
static {
string0 = "George";
}
public static String randomName = initRandomName();
private static String initRandomName() {
return "Mr. " string0;
}
}
… но это довольно хрупко, полагаться на то, что никто не переупорядочивает членов класса, не понимая последствий.
Если вам действительно нужна такая инициализация, я бы предложил объявить все поля без их инициализации, а затем инициализировать все в блоке статического инициализатора, чтобы порядок был очевиден.
Комментарии:
1. Спасибо. Ваш ответ действительно полезен. Я хотел знать, как работает статическая инициализация, и теперь я ее понял.