我们总会遇到这样的代码,
`public class Test {
public int a = 1;
}
`
当new一个这样的对象后,里面就有一个叫做‘a’的整型变量,其值为1;
但是new这个对象的具体过程,在这之前,我并不是非常的清楚,当老师出了一道有关知识点的面试题后,我才搞懂其中的顺序,废话不多说,上题:
public class Parent {
public int a = 11;
public Parent() {
printA();
}
public void printA(){
System.out.println(a);
}
}
public class Child extends Parent{
public int a = 250;
{
a = 251;
}
public Child() {
super();
}
@Override
public void printA() {
System.out.println(a);
}
public static void main(String[] args) {
new Child();
}
}
写出程序的运行结果
大家可以先自己做一下虚拟机,编译运行一下,看看结果是多少
==============萌萌哒分割线==================
运行结果为
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
0
我刚开始对这个结果也十分的不理解,现在我为大家解释一下:
当为继承关系的两个类进行编译运行的时候,首先虚拟机会先执行所有的静态数据块,先父类静态数据块后子类静态数据块,然后再执行父类的非静态数据块和父类的构造方法,最后执行子类的非静态数据块和构造方法。
而且,在Child类中出现的这条语句“public int a = 250;
”,只是先分配了空间,在父类的构造方法结束之前,并不会进行“250”的赋值操作,当成员变量未进行初始化时,虚拟机会对其进行默认值得赋值操作,所以其值一开始是
“0”
我们再来看代码,将代码的执行过程仔细的过一遍:
- 第一步,当代码执行到main方法时,new了一个Child对象,虚拟机在内存中分配了空间,并有两个名为“a”的变量,为了区别表示,分别叫为“pa”和“ca”。随后虚拟机先执行所有的静态数据块,但此时并没有,所以没有显式的效果
- 第二步开始执行Parent类的非静态语句块和构造方法,当Parent的父类(Object)完成初始化后,“pa”变量被赋值为11,然后调用了“printA();”,由于Child类已经重写了Parent类中的printA()方法,所以现在调用的是Child类中的printA()方法,而此时变量“ca”还为默认值0,所以调用方法后,输出结果为0;
第三步,执行Child类的非静态语句块和构造方法,此时父类的构造方法已经执行结束(相当于“super();”语句执行完毕),所以变量“ca”被赋值250,随后执行非静态语句块,“ca”的值被改成为251,然后语句“new Child();”语句执行完毕;
这就是完整的执行过程