将 Class 文件
加载到 JVM 内存
,整个生命周期:加载、连接(验证、准备、解析)、初始化、使用、连接
其中,解析阶段,某些情况,可在初始化之后开始
在初始化阶段,发生以下情况,会立即对类进行初始化
1 new、访问 static 方法、字段
new
class Son {
static {
System.out.println("Son.static initializer");
}
}
public class Main {
public static void main(String[] args) {
new Son();
}
}
Son.static initializer
访问 static 字段
class Son {
static int age = 10;
static {
System.out.println("Son.static initializer");
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Son.age);
}
}
Son.static initializer
10
访问 static 方法
class Son {
static {
System.out.println("Son.static initializer");
}
static void eat(){
System.out.println("Son.eat");
}
}
public class Main {
public static void main(String[] args) {
Son.eat();
}
}
Son.static initializer
Son.eat
2 反射
Class.forName
class Son {
static {
System.out.println("Son.static initializer");
}
}
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("cn.zhang.Son");
}
}
Son.static initializer
Son.class
class Son {
static {
System.out.println("Son.static initializer");
}
}
public class Main {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Son.class.newInstance();
}
}
Son.static initializer
3 初始化类时:Main、Father、Son
class Father {
static {
System.out.println("Father.static initializer");
}
}
class Son extends Father {
static {
System.out.println("Son.static initializer");
}
}
public class Main {
static {
System.out.println("Main.static initializer");
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
new Son();
}
}
Main.static initializer
Father.static initializer
Son.static initializer
4 代理
interface Foo {
void dothings();
}
class FooImpl implements Foo {
static {
System.out.println("FooImpl.static initializer");
}
public void dothings() {
}
public static void main(String[] args) {
Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
FooImpl.class.getInterfaces(),
(proxy, method, args1) -> method.invoke(new FooImpl(), args1));
}
}
FooImpl.static initializer
不会触发初始化的情况
子类引用父类静态字段
class Father {
static {
System.out.println("Father.static initializer");
}
static int age = 30;
}
class Son extends Father {
static {
System.out.println("Son.static initializer");
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Son.age);
}
}
Father.static initializer
30
new 数组
class Son {
static {
System.out.println("Son.static initializer");
}
}
public class Main {
public static void main(String[] args) {
Son[] sons = new Son[10];
}
}
什么都不打印
常量传播优化
常量引用 -> 自身常量池引用
class Son {
static {
System.out.println("Son.static initializer");
}
static final int age = 30;
}
public class Main {
public static void main(String[] args) {
System.out.println(Son.age);
}
}
30
参考
- 深入理解JVM虚拟机 第7章