java类加载过程为加载→验证→准备→解析→初始化五阶段,其中初始化是执行静态代码和静态赋值的起点,仅在主动引用时触发。

Java程序启动时,JVM并不是一上来就执行main方法,而是先完成类加载与初始化的一整套流程。这个过程直接决定了静态变量、静态代码块、普通代码块和构造器的执行顺序——理解它,才能真正看懂Java程序“从哪开始、怎么动起来”。
类加载的五个关键阶段
一个类从磁盘上的.class文件变成可运行的对象,要经历:加载 → 验证 → 准备 → 解析 → 初始化。其中前四步统称“连接”,而初始化才是真正执行用户代码的起点。
-
加载:JVM根据全限定名(如com.example.Main)找到.class字节码,读入内存,在方法区构建运行时结构,并在堆中创建对应的
Class对象 - 验证:检查字节码是否合规(魔数、版本、语义、指令逻辑等),防止恶意或损坏的类破坏虚拟机
-
准备:为
static变量分配内存并设默认值(如int→0,Object→null),但final static常量会在此阶段直接赋值(如public static final int PORT = 8080;) - 解析:把常量池里的符号引用(比如类名、方法名字符串)替换成内存中的真实地址(直接引用)
-
初始化:执行
<clinit>()</clinit>方法——这是编译器自动生成的静态初始化器,合并了所有静态变量赋值语句和静态代码块,按源码书写顺序执行
静态代码块和静态变量的执行时机
它们只在类的初始化阶段执行,且仅一次。触发初始化的“主动引用”包括:new实例、访问静态字段(非final常量)、调用静态方法、反射获取Class、子类初始化时父类先行初始化、以及主类被JVM选为入口。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 静态变量声明与静态代码块按源码自上而下执行,谁在前面谁先跑
- 静态变量的显式初始化(如
static String s = init();)是在初始化阶段调用方法,不是准备阶段 - 访问
final static基本类型或字符串字面量(如Math.PI)不会触发类初始化,因为值已在编译期确定并内联
继承体系下的完整执行顺序
当创建子类实例(如new Child())时,整个链条被拉起:
- 先触发父类初始化(若未初始化):父类静态块 → 父类静态变量赋值 → 子类静态块 → 子类静态变量赋值
- 再进入实例创建:父类普通代码块 → 父类构造器 → 子类普通代码块 → 子类构造器
- 注意:普通代码块(即
{...})属于实例级别,每次new都会执行;静态代码块只在类加载完成初始化时跑一次
main方法作为入口的特殊性
JVM启动时,会把命令行指定的主类(含public static void main(String[])的那个类)作为第一个要初始化的类。也就是说,main方法所在的类,其静态部分(静态变量、静态块)会在程序真正开始前全部执行完毕。
- 如果
main里第一行是System.out.println(Child.n);,那Child类会立即初始化(包括它的父类) - 如果
main里只写new Parent().doSomething();,那么Parent类初始化,Child类不会被加载(除非后续代码触发) - 类加载本身不等于初始化;只有满足“主动引用”条件时,才会走到初始化这一步
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










