Java的类加载

一、什么是类加载时初始化?

类加载时初始化 指的是当Java虚拟机(JVM)第一次加载一个类时,会执行该类的静态成员初始化 和静态代码块 。这是类生命周期中的一个重要阶段,发生在类被首次使用之前。

二、类加载的三个时机

一个类在以下情况下会被加载:

1. 创建类的实例(最常见)

2. 访问类的静态成员

3. 使用反射

三、初始化阶段的具体内容

1. 静态变量的初始化

执行顺序:

  1. 先声明所有静态变量(分配内存空间)
  2. 按照代码中的顺序依次初始化静态变量和静态代码块

四、完整的类加载和初始化过程

1. 类加载的三个阶段

详细过程:

  1. 加载(Loading) :
    • 通过类全限定名找到.class文件
    • 读取字节码到内存
    • 在堆中创建Class对象
  2. 链接(Linking) :
    • 验证:检查字节码格式、安全性
    • 准备:为静态变量分配内存,设置默认值
    • 解析:将符号引用转为直接引用
  3. 初始化(Initialization) :
    • 执行静态变量赋值
    • 执行静态代码块
    • 执行父类的初始化(如果有)

2.实列展示

五、总结要点

  1. 类加载时初始化是JVM加载类的一个必要阶段
  2. 主要初始化静态成员(静态变量和静态代码块)
  3. 只执行一次(首次使用类时)
  4. 先父类后子类(继承关系)
  5. 与对象创建无关(静态初始化早于对象创建)
  6. 有特定的触发条件和执行顺序

例子:

java 复制代码
class Parent {
    // 父类静态变量
    static {
        System.out.println("父类静态代码块执行");
    }

    static int parentStatic = initParentStatic();

    private static int initParentStatic() {
        System.out.println("父类静态变量初始化");
        return 100;
    }

    // 父类实例变量
    {
        System.out.println("父类构造代码块执行");
    }

    int parentInstance = initParentInstance();

    private int initParentInstance() {
        System.out.println("父类实例变量初始化");
        return 200;
    }

    // 父类构造方法
    public Parent() {
        System.out.println("父类构造方法执行");
    }
}

class Child extends Parent {
    // 子类静态变量
    static {
        System.out.println("子类静态代码块执行");
    }

    static int childStatic = initChildStatic();

    private static int initChildStatic() {
        System.out.println("子类静态变量初始化");
        return 300;
    }

    // 子类实例变量
    {
        System.out.println("子类构造代码块执行");
    }

    int childInstance = initChildInstance();

    private int initChildInstance() {
        System.out.println("子类实例变量初始化");
        return 400;
    }

    // 子类构造方法
    public Child() {
        System.out.println("子类构造方法执行");
    }
}

public class FullInitializationDemo {
    public static void main(String[] args) {
        System.out.println("=== 第一次创建Child对象 ===");
        Child child1 = new Child();
        System.out.println("\n===== 第二次创建Child对象 ===");
        Child child2 = new Child();
    }
}

输出结果:

观察:

  1. 静态部分只执行一次(第一次加载类时)
  2. 先父类后子类(静态→父类静态→子类静态)
  3. 实例部分每次创建对象都执行

完整顺序:

  1. 父类静态变量和静态代码块(按代码顺序)
  2. 子类静态变量和静态代码块(按代码顺序)
  3. 父类实例变量和构造代码块(按代码顺序)
  4. 父类构造方法
  5. 子类实例变量和构造代码块(按代码顺序)
  6. 子类构造方法

记忆口诀:

  • 先静态后实例
  • 先父类后子类
  • 先变量后代码块
  • 先代码块后构造方法
相关推荐
白杨尚青13 分钟前
C++进阶篇(二):多态——虚函数、重写、虚函数表与三个经典坑(附完整代码仓库)
开发语言·c++·多态·虚函数·重写·动态绑定
考虑考虑7 小时前
JDK26中的Map.ofLazy
java·后端·java ee
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 14 章 MCP 服务端(上):注解式实现与工具来源
java·人工智能·开源
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 15 章 MCP 服务端(下):三种协议形态、Streamable 传输与状态管理
java·人工智能·开源
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 16 章 向量存储(上):`VectorStore` 接口体系、`BatchingStrategy`
java·人工智能·开源
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 12 章 工具循环的流式形态、Usage 累加与扩展体系
java·人工智能·开源
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 23 章 模型供应商实现:从 `OpenAiSetup` 到 Bedrock
java·人工智能·开源
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 06 章 内置 Advisor 全景:13 个实现逐个剖到源码级
java·人工智能·开源
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 03 章 消息体系与 Prompt:不可变模型、`ChatOptions` 与模板渲染
java·人工智能·开源
鶴哥只手遮天10 小时前
Spring AI 2.0.1 深度解析-第 24 章 生产实践与 2.x 迁移:陷阱清单、AOT 与调优
java·人工智能·开源