我最近遇到过这些问题,但在StackOverflow上找不到答案;
根据Meta的建议,我将发布我对此问题的回答。
答案 0 :(得分:7)
在Java中,类变量在following order:
中初始化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 Language Specification。
中指定