前言
java version "1.8.0_172"
Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)
概念
静态成员:
包括静态变量,静态成员方法以及静态代码块。
类的初始化:
对类成员变量(静态成员变量)进行赋值的过程。
对象的初始化
对普通成员变量进行赋值的过程。
结论
静态成员之间没有执行优先级,只会按照顺序执行。
代码分析
public class Father {
static String str1 = "父类属性str1";
static String str2 = getStr2();
static {
System.out.println(str2);//这里能够使用str2变量,说明代码块和变量之间没有优先级
System.out.println("父类代码块1");
// System.out.println(str3);//这里使用str3报错说明,代码块和变量之间是按照先后顺序执行的
}
// static String str3 = "父类属性str3";
public static String getStr2() {
System.out.println("父类方法getStr2");
return "父类属性str2";
}
static {
System.out.println("父类代码块2");
}
public static void getStr3() {
System.out.println("父类方法getStr3");
}
}
类和对象混合初始化
分析总结放到了最后。
分析过程代码
public class Son extends Father{
String comStr1 = getSonComStr1();
String comStr2 = "子类静态变量2";
static String staStr1 = getStaStr1();
static String staStr2 = "子类静态变量2";
private String getSonComStr1() {
System.out.println("子类普通方法1");
return "子类普通变量1";
}
private static String getStaStr1() {
System.out.println("子类静态方法1");
return "子类静态变量1";
}
{
System.out.println("子类普通代码块1");
}
static {
System.out.println("子类静态代码块1");
}
public Son() {
//super();//每一个构造方法的首行都有一个隐藏的super()语句,调用父类无参构造
System.out.println("子类无参构造函数");
}
{
System.out.println("子类普通代码块2");
}
static {
System.out.println("子类静态代码块2");
}
}
class Father {
String comStr1 = getFatherComStr1();
String comStr2 = "父类静态变量2";
static String staStr1 = getStaStr1();
static String staStr2 = "父类静态变量2";
private String getFatherComStr1() {
System.out.println("父类普通方法1");
return "父类普通变量1";
}
private static String getStaStr1() {
System.out.println("父类静态方法1");
return "父类静态变量1";
}
{
System.out.println("父类普通代码块1");
}
static {
System.out.println("父类静态代码块1");
}
public Father() {
//super();//每一个构造方法的首行都有一个隐藏的super()语句
System.out.println("父类无参构造函数");
}
{
System.out.println("父类普通代码块2");
}
static {
System.out.println("父类静态代码块2");
}
}
结果展示
父类静态方法1
父类静态代码块1
父类静态代码块2
子类静态方法1
子类静态代码块1
子类静态代码块2
父类普通方法1
父类普通代码块1
父类普通代码块2
父类无参构造函数
子类普通方法1
子类普通代码块1
子类普通代码块2
子类无参构造函数
分析过程
new Son();
- 扫描子类和父类中的静态成员,并进行优先初始化。这里输出
父类静态方法1
父类静态代码块1
父类静态代码块2
子类静态方法1
子类静态代码块1
子类静态代码块2
这里其他静态成员也初始化了,但是并没有输出。并且从这里可以看出,先初始化父类静态成员,后初始化子类静态成员。
3. 进入子类无参构造方法,在首行遇到super()
public Son(){
super();//执行到这,然后进入该方法。
}
- 进入super()方法。
public Father() {
//super();//每一个构造方法的首行都有一个隐藏的super()语句
System.out.println("父类无参构造函数");
}
注意,这里Father类的无参构造首行仍然有一个super(),执行Object类的无参构造。
5. 父类无参构造中的super()执行结束,回到父类,从头开始初始化,一直到最后。届时,父类中所有成员均被初始化。(这一步仅初始化的是非静态成员,因为在在步骤2中父类中的所有静态成员已被提前初始化。)
class Father {
String comStr1;//即来到这个地方。
...
}//然后一直到结束,父类中的所有成员均被初始化。
该步骤执行输出:
父类普通方法1
父类普通代码块1
父类普通代码块2
- 父类所有成员初始化结束,回到父类无参构造super()处,继续向下父类无参构造方法中的语句。
public Father(){
//super();
System.out.println("父类无参构造函数");//执行这步。
}
输出:
父类无参构造函数
- 这时父类中所有代码执行完毕,回到子类,从子类类的首行开始向下执行,末尾结束。这步同步骤5。
public class Son extends Father{
String comStr1 = getSonComStr1();//由此开始执行。
...
}
输出:
子类普通方法1
子类普通代码块1
子类普通代码块
- 子类所有成员初始化完毕,回到子类无参super()处,继续向下执行无参构造中的代码。
public Son() {
//super();//每一个构造方法的首行都有一个隐藏的super()语句,调用父类无参构造
System.out.println("子类无参构造函数");//从此往下执行
}
输出:
子类无参构造函数
- 致此,结束,返回main方法。
总结
执行顺序:
静态成员(父类>子类) > 父类成员和方法(构造方法>父类其他)> 子类成员和方法(构造方法>子类其他)
1. 针对一个类:静态>构造>普通。
2. 有静态先执行静态,不管是子类静态还是父类静态。
3. 同级别间没有优先级,按照顺序执行。
4. 父类>子类