Javase学习-03类的加载顺序
Java类的加载顺序
1. static
以上是static方法《Java编程思想》P86页描述static方法特殊之处的一段话,简而言之就是:
显然用static关键字修饰的变量或方法不需要依赖对象来访问,只要类加载进内存,就可以用类名直接访问
static可以用来修饰类的成员变量,类的成员方法,还可以编写static代码块来优化程序性能
当class文件被加载进内存,开始初始化时,被static修饰的变量或方法立即被分配了内存,而其他的变量或方法是在创建对象后才被分配了内存
2.案例说明
/**
* @Author: TSCCG
* @Date: 2021/07/13 10:26
*/
public class Test01 {
/**
* 程序入口
*/
public static void main(String[] args) {
Son son = new Son();
}
}
/**
* 父类
*/
class Father {
// 父类的静态变量
private static String NAME = "小头爸爸";
// 父类的静态代码块
static {
System.out.println("父类的静态属性:" + NAME);
System.out.println("父类的静态代码块");
}
// 父类的非静态属性
private String hobby ="抽烟";
// 父类的非静态代码块
{
System.out.println("父类的非静态属性:" + hobby);
System.out.println("父类的非静态代码块");
}
//父类的无参构造方法
public Father() {
System.out.println("父类的构造方法");
}
}
/**
* 子类
*/
class Son extends Father{
// 子类的静态变量
private static String NAME = "大头儿子";
// 子类的静态代码块
static {
System.out.println("子类的静态属性:" + NAME);
System.out.println("子类的静态代码块");
}
// 子类的非静态属性
private String hobby = "打豆豆";
// 子类的非静态代码块
{
System.out.println("子类的非静态属性:" + hobby);
System.out.println("子类的非静态代码块");
}
//子类的无参构造方法
public Son() {
super();
System.out.println("子类的构造方法");
}
}
结果:
父类的静态属性:小头爸爸
父类的静态代码块
子类的静态属性:大头儿子
子类的静态代码块
父类的非静态属性:抽烟
父类的非静态代码块
父类的构造方法
子类的非静态属性:打豆豆
子类的非静态代码块
子类的构造方法
3.总结
我们想一下以上代码运行的过程:
- 首先要找main方法,main方法是程序运行的入口,但在运行main方法之前,必须要先加载Son类。
- 加载Son类时,发现Son类继承于Father类,所以就先加载Father类。
- 加载Father类时,发现静态变量和静态代码块,于是执行了静态变量和静态代码块(执行static修饰的代码块顺序取决于代码的先后顺序,并且只执行一次)。
- 然后继续加载Son类,发现Son类中也有静态变量和静态代码块,便执行static修饰的代码块。
- 加载完所需类后,开始执行main方法。
- 在main方法中执行new Son()时,会调用子类的构造方法,子类的构造方法默认先调用父类的无参构造方法。
- 父类的无参构造方法执行,发现非静态属性和非静态代码块,于是加载非静态属性和非静态代码块。最后再执行父类无参构造方法中的最后的代码块。
- 然后子类的构造方法执行,发现非静态属性和非静态代码块,于是加载非静态属性和非静态代码块,最后再执行子类无参构造方法中的最后的代码块。
注意:
- 为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次
- 以上实例变量的初始化语句经过编译器处理后,会合并到构造器中,其中定义变量语句转换得到的赋值语句总是位于构造器的所有语句之前