Компилятор сначала обработает объявление статической переменной, а уже потом будут выполнены блоки статической инициализации и/или присваивания статической переменной в порядке их определения в коде. В частности, это приведёт к тому, что присваивание 10 в первом блоке будет утеряно.
Порядок таков:
- Объявляется статическая переменная
i
.
- Выполняется первый блок статической инициализации
static {i = 10;}
- Выполняется присваивание при объявлении переменной
static int i = 0
- Выполняется второй блок статической инициализации
static {++i; // 1}
Но если бы вы попытались обратиться в первом блоке статической инициализации к переменной (например, System.out.println(i);
), тогда возникла бы ошибка компиляции, связанная с обращением к неопределённой переменной.
static {
System.out.println("1st block in: i=" + i); // error: illegal forward reference
i = 10;
System.out.println("1st block out: i=" + i); // error: illegal forward reference
}
static int i = 0;
См. Which cases allow forward referencing in static initializer blocks?
При этом, если при инициализации i = 0
убрать тип данных будет ошибка,
Разумеется, тогда у вас получается неправильно объявленная статическая переменная (не указан тип).
и если указать тип данных только во втором блоке тоже будет ошибка.
В таком случае вы объявляете локальную переменную внутри блока статической инициализации, изменения в которой не повлияют на значение переменной класса.
Модифицированный пример:
static {
int i = 10;
System.out.println("1st block out: i=" + i); // локальная переменная блока 1
}
static int i = 5;
static {
System.out.println("2nd block in: i=" + i); // переменная класса
int i = 20;
System.out.println("2nd block out: i=" + i); // локальная переменная блока 2
}
public static void main(String[] args) {
System.out.println(i);
}
Результат:
1st block out: i=10
2nd block in: i=5
2nd block out: i=20
5