В Java переменные класса инициализируются в в следующем порядке :
- Статические переменные ваших суперклассов
- Все статические переменные этого класса имеют свои значения по умолчанию .
- Статические переменные и блоки статической инициализации в порядке объявления.
- Переменные экземпляра ваших суперклассов
- Все переменные экземпляра этого класса установлены на значения по умолчанию .
- Переменные экземпляра и блоки инициализации на уровне экземпляра в порядке объявления
1 & 2 выполняются только в первый раз, когда создается экземпляр класса.
Итак, учитывая следующий код:
class Test
extends TestSuper
{
final int ti1;
final int ti2 = counter ++;
{ ti1 = counter ++; }
static final int ts1;
static final int ts2 = counter ++;
static { ts1 = counter ++; }
public static void main(String[] argv) {
Test test1 = new Test();
printTest(test1);
Test test2 = new Test();
printTest(test2);
}
private static void printTest(Test test) {
System.out.print("ss2 = " + test.ss2);
System.out.print(", ss1 = " + test.ss1);
System.out.print(", ts2 = " + test.ts2);
System.out.println(", ts1 = " + test.ts1);
System.out.print("si2 = " + test.si2);
System.out.print(", si1 = " + test.si1);
System.out.print(", ti2 = " + test.ti2);
System.out.println(", ti1 = " + test.ti1);
System.out.println("counter = " + test.counter);
}
}
class TestSuper
{
static int counter = 0;
final int si1;
final int si2 = counter ++;
{ si1 = counter ++; }
static final int ss1;
static final int ss2 = counter ++;
static { ss1 = counter ++; }
}
Тогда мы получим следующий вывод:
ss2 = 0, ss1 = 1, ts2 = 2, ts1 = 3
si2 = 4, si1 = 5, ti2 = 6, ti1 = 7
counter = 8
ss2 = 0, ss1 = 1, ts2 = 2, ts1 = 3
si2 = 8, si1 = 9, ti2 = 10, ti1 = 11
counter = 12
Из этого вывода видно, что поля инициализируются в порядке, указанном в списке.
Теперь, что касается второго вопроса, может ли переупорядочение полей изменить поведение класса. Да, изменяя порядок полей, вы изменяете порядок инициализации полей. Теперь, в конкретном случае, когда все поля независимы, это не повлияет на наблюдаемое поведение, однако всякий раз, когда поля не являются независимыми, например, в приведенном выше коде, изменение порядка полей может изменить их инициализированные значения.
Например, если три строки:
static final int ss1;
static final int ss2 = counter ++;
static { ss1 = counter ++; }
изменены на:
static final int ss1;
static { ss1 = counter ++; }
static final int ss2 = counter ++;
Тогда вывод изменится на:
ss2 = 1, ss1 = 0, ts2 = 2, ts1 = 3
si2 = 4, si1 = 5, ti2 = 6, ti1 = 7
counter = 8
То есть ss2
и ss1
будут изменять значения.
Причина этого заключается в том, что это поведение указано в Спецификации языка Java .