类初始化过程,实例初始化过程代码的执行顺序
首先有以下代码:
public class ClassTest {
public static void main(String[] args) {
Son s1=new Son();
System.out.println();
Son s2=new Son();
}
static {
System.out.println("(11)main方法所在的类");
}
}
class Father{
private int i=test();
private static int j=method();
static {
System.out.println("(1)父类中静态代码块");
}
Father(){
System.out.println("(2)父类构造方法");
}
{
System.out.println("(3)父类代码块");
}
public int test() {
System.out.println("(4)父类成员方法-赋值语句");
return 1;
}
public static int method() {
System.out.println("(5)父类静态成员方法-赋值语句");
return 1;
}
}
class Son extends Father{
private int i=test();
private static int j=method();
static {
System.out.println("(6)子类中静态代码块");
}
Son(){
System.out.println("(7)子类构造方法");
}
{
System.out.println("(8)子类代码块");
}
public int test() {
System.out.println("(9)子类成员方法-赋值语句");
return 1;
}
public static int method() {
System.out.println("(10)子类静态成员方法-赋值语句");
return 1;
}
}
请写出以上代码的运行结果。
题目解析:
首先我们可看到我们定义了一个Father类和它的子类Son类,它们类中的结构大致一致,分别有静态代码块,构造方法,代码块,成员方法,静态成员方法,要求输出它们的执行先后顺序。
执行结果:
也就是:
第一次实例化子类:
- 父类静态成员方法->父类静态代码块->子类静态成员方法->子类静态代码块->子类私有成员方法
- ->父类代码块->父类构造方法->子类私有成员方法->子类代码块->子类构造方法
- 第二次实例化:
- 子类成员方法->父类代码块->父类构造方法->子类成员方法->子类代码块->子类构造方法
类初始化过程:(5)(1)(10)(6)过程,(11)暂且排除
- 一个类要创建实例需要先加载并初始化该类。
- 注意:main方法所在的类需要先加载和初始化(所以11先执行)
- 一个子类要初始化需要先初始化父类(所以第一次new Son类时会先初始化Father类)
- 类初始化会调用clinit()方法 :
-
由静态类变量显示赋值代码和静态代码块组成 只执行一次
-
赋值代码和静态代块的执行顺序会由它们的位置决定
- clinit方法只执行一次。
实例初始化过程: (9)(3)(2)(9)(8)(7)过程
- 调用init()方法 可能可能有多个,几个构造器就有几个init()方法
- 由非静态实例变量显示赋值代码和非静态代码块组成
- super()->非静态赋值->非静态代码块->无参构造器,test()会覆盖父类中的代码,静态的method不能被重写。
方法的重写: 过程(9)
- Son继承的父类的test方法,实际上重写了父类的test方法,所以i=test()其实是执行的是子类重写的父类的方法。
- 静态的method方法不能被重写,final修饰的方法,private修饰的子类不可见的方法也不能被重写。
对象的多态性:
- 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码。
- 非静态方法默认的调用对象是this。