类加载,在 java 基础文档的第一篇内容中就已经提到过,会经过以下流程:
- java 源文件 经过 编译,生成 class 字节码文件
- 进入到类加载器
- 再经过字节码校验器
- 解释器
- 最终运行在操作系统平台
也就是说类加载动作发生在程序代码执行之前。但在代码当中有一个东西是跟类加载息息相关的,就是类里面 static 所修饰的内容。
其中,特别是静态代码块中的代码是在加载期就被执行的,所以我们需要知道 static 静态代码块在继承关系下所体现出来的特性。
创建父类对象时静态代码块的现象
当有父子两类存在,只创建父类实例时的现象:
// Parent.java
public class Parent {
public String name;
public int age;
public String gender = "male";
// 静态代码块
static {
System.out.println("父类的静态代码块被执行");
}
public Parent() {
System.out.println("父类的无参构造被执行");
}
public Parent(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
System.out.println("父类构造函数被调用");
}
}
// Child.java
public class Child extends Parent {
static {
System.out.println("子类的静态代码块被执行");
}
public Child() {
System.out.println("子类的无参构造被执行");
}
public Child(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
System.out.println("子类构造函数被调用");
}
}
// TestMain.java
Parent p = new Parent(); // 输出:父类父类的静态代码块被执行 父类的无参构造被执行
由此可以看出,当程序中需要 使用 到哪个类,就会加载哪个类,也就会执行它的静态代码块。
创建子类对象时静态代码块的现象
同样的文档结构,创建子类时,静态代码块的现象:
此时会发现,当 new 子类时,父类、子类都会被加载,或者说 new 子类时也会自动加载它的父类。子类代码中有一部分属性行为是共有于父类、继承于父类的,所以单加载子类是不够的,若不加载父类那么共有部分则会信息丢失。
所以加载的顺序:先父类再子类。
创建父子类对象时静态代码块的现象
那如果同时创建父类对象和子类对象呢?观察静态代码块的现象:
当父类子类同时创建对象,类只需要加载一次,或者说 一个类只会被加载一次,那么创建子类时就不需要重复加载父类。
现在的 java 虚拟机在加载时采用 JIT(just in time) ——即时加载。它不会预先把要用的类进行加载,而是边执行边加载。