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. 子类构造方法

记忆口诀:

  • 先静态后实例
  • 先父类后子类
  • 先变量后代码块
  • 先代码块后构造方法
相关推荐
小羊没烦恼!4 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里4 天前
java中的继承和多态的区别
java
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕4 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码4 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖4 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时4 天前
01-06-A-JVM排查实战详解
java·jvm
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
vipxieliang4 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
C语言小火车4 天前
C/C++ 为什么需要编译器?
开发语言·c++