昨天看到群里面有人分享了一道题目,我答错了,于是趁机了解了下Java的类/对象初始化过程:
程序A主要考察的是 类实例初始化 。简单验证了下,类实例初始化过程如下:
程序B考察的则是 类初始化 。类初始化的过程如下:
但是我们必须做到 面向接口编程,而不是面向实现编程(Program to an ‘interface’, not an ‘implementation’) 。
于是就得看看 Java Language Specification 了。其中 类初始化过程 如下:
可以看到JLS确实规定了父类先初始化(7)、static块和类变量赋值按照文本顺序来(9)。
然后看看 类实例的初始化 :
JLS特意提到,如果子类覆盖了父类的方法,则在构造函数中, 调用的方法也是子类的 。
接下来一个一个看代码:
// 程序A
// 父类
class Parent {
int i = 1;
Parent() {
System.out.println(i);
int x = getValue();
System.out.println(x);
}
{i = 2;}
protected int getValue() {return i;}
}
// 子类
class Son extends Parent {
int j = 1;
Son() {j = 2;}
protected int getValue() {return j;}
}
class Test {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.getValue());
}
}
所以,程序A的输出是:
接下来看程序B:
// 程序B
public class MagimaTest {
public static void main(String[] args) {
magimaFunction();
}
static MagimaTest st = new MagimaTest();
static {
System.out.println("1");
}
{
System.out.println("2");
}
MagimaTest() {
System.out.println("3");
System.out.println("a=" + a + ",b=" + b);
}
public static void magimaFunction() {
System.out.println("4");
}
int a = 110;
static int b = 112;
}
所以输出是:
2 3 a=110,b=0 1 4
好了,看完了解析。那么我再出一个题目吧: 如果将程序B中的MagimaTest.b改为final的,输出会变化吗?