下面这个案例整合了继承,静态成员,构造器的执行顺序以及就近原则问题的分析,看到很多面试题经常会出此类的题目,具体看例子。
父类:
public abstract class Fu {
static int count=3;
int a=3;
static{
System.out.println("父类的静态代码块");
}
public Fu() {
a=5;
System.out.println("执行父类的构造方法");
}
public void display(){
System.out.println("父类的diaplay()方法");
System.out.println(a);
show();
}
public void show(){
System.out.println("父类的show方法");
}
}
子类:
public class Zi extends Fu {
static int count=10;
int a=6;
static{
System.out.println("子类的静态代码块");
}
public Zi() {
System.out.println("执行子类的构造方法");
}
public void show(){
System.out.println("子类的show方法");
System.out.println(a);
}
}
测试类:
public class Test {
static{
System.out.println("测试类的静态代码块!");
}
public static void main(String[] args) {
Zi zi = new Zi();
zi.display();
}
}
执行main(),会得到怎样的结果呢?看控制台的输出结果:
测试类的静态代码块! 1
父类的静态代码块 2
子类的静态代码块 3
执行父类的构造方法 4
执行子类的构造方法 5
父类的diaplay()方法 6
5 7
子类的show方法 8
6 9
下面是关于执行步骤的分析:
1.jvm加载含有main()的类,打印结果1
2.执行main(),创建子类对象,会在创建子类对象之前调用父类无参的构造方法,所以初始化父类,打印结果2
3.初始化完父类,初始化子类,打印结果3
4.执行父类的构造方法,完成父类的初始化,但不会创建父类对象(抽象类,即使不是抽象类,也不会创建父类对象,只有new,才会创建对象)。打印结果4
5.执行子类的构造方法,准备创建子类对象,打印结果5
6,调用子类的display()方法,子类没有重写,所以调用父类的diaplay()方法,打印结果6
7.然后输出父类的成员,就近原则(看图)打印结果7
8.在display()中调用show()方法,子类覆盖了其show(),子类的空间也有,调用的是子类的show()方法。打印结果8
9.最后就近,打印子类的成员,打印结果9
为此我还为继承的关系画了个内存图
关于内存图的需要解释的地方:子类继承父类时,创建子类对象以后,会在堆内存中给子类对象分配一块内存空间,这个子类中空间中还存有一个父类的空间装着父类的一些成员。可以总结为,一块地址,两片空间。