看一段代码:
public class main_class {
public static void main(String[] args){
new c2();
}
}
class c1{
String name="aaaaaa";
//父类构造函数
public c1(){
print();
}
//该构造函数自始至终就没有被调用过
public void print(){
System.out.println(name);
}
}
class c2 extends c1{
String name="asdg";
//构造函数:
public c2(){
System.out.println(name);
}
//重写父类中的print()函数
public void print(){
System.out.println(name);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
输出:
null
asdg
- 1
- 2
- 3
分析:
1.初始化c2()时,先初始化c2的父类:c1()
初始化c1()的静态变量和静态代码块
初始化c2()的静态变量和静态代码块
2.初始化c1()的非静态变量,初始化父类的构造函数。
如果父类的构造函数中调用的方法被子类重写,那么调用的会是子类的方法。
3.初始化c2()的非静态变量,初始化子类的构造函数。
new c2();在创造派生类的过程中首先创建基类对象,然后才能创建派生类。
创建基类即默认调用c1()方法,在方法中调用print()方法,由于派生类中存在此方法,则被调用的print()方法是派生类中的方法,此时派生类还未构造,所以变量name的值为null
先成员变量再构造方法,先父类再子类
多态表现:有同名方法执行子类的
执行 c1 b = new c2();时,由于多态 b编译时表现为c1类特性,运行时表现为c2类特性,
c1 b = new c2();;不管是哪种状态都会调用c1构造器执行 print()方法;
执行方法时,由于多态表现为子类特性,所以会先在子类是否有 print();
而此时子类尚未初始化(执行完父类构造器后才会开始执行子类),
如果有 就 执行(此时, 因为还没有调用子类构造函数, 所以子类的 name输出为 null),没有再去父类寻找。