默谷资源网

专业网站建设资源库

普通java对象的实例化过程

在 Java 中,普通对象(非数组、非基本类型)的实例化过程通过 new 关键字触发,主要分为以下步骤:

类加载检查

  • JVM 检查类是否已被加载(ClassLoader 加载过程)。
  • 若未加载,则先执行类加载(加载 → 验证 → 准备 → 解析 → 初始化)。

内存分配

  • JVM 在 堆内存 中为对象分配空间(对象大小在类加载时已确定)。
  • 分配方式:
    • 指针碰撞(堆内存规整时,移动指针划分空间)。
    • 空闲列表(堆内存不规整时,从空闲内存块列表分配)。

初始化默认值

  • 为对象的所有成员变量赋予类型默认值
    • int/long/short/byte0
    • float/double0.0
    • booleanfalse
    • 引用类型 → null

设置对象头(Object Header)

  • 在对象内存布局中写入元数据:
    • Mark Word:哈希码、GC 分代年龄、锁状态等。
    • 类型指针:指向方法区中的类元数据(Class Metadata)。
    • 若启用压缩指针(-XX:+UseCompressedOops),类型指针占 4 字节,否则占 8 字节。

执行初始化代码

  • 按顺序执行以下初始化操作:
    • 实例变量显式赋值(如 private String name = "Tom";)。
    • 实例初始化块(Instance Initializer Block)
  {
      System.out.println("执行实例初始化块");
  }
    • 构造函数(Constructor)
      • 先隐式调用父类构造函数(super()),递归至 Object 类。
      • 再执行子类构造函数的剩余代码。

关键流程图解

new 关键字触发
     ↓
类加载检查(未加载则加载类)
     ↓
在堆中分配内存
     ↓
初始化成员变量为默认值(0/null/false)
     ↓
设置对象头(Mark Word + 类型指针)
     ↓
执行初始化代码:
    1. 显式赋值(name = "Tom")
    2. 实例初始化块 {}
    3. 构造函数(先 super() → 再子类构造代码)

示例代码分析

class Parent {
    int a = 10; // 显式赋值
    { System.out.println("Parent 实例块"); }
    Parent() { System.out.println("Parent 构造函数"); }
}

class Child extends Parent {
    int b = 20; // 显式赋值
    { System.out.println("Child 实例块"); }
    Child() {
        super(); // 隐式调用父类构造函数
        System.out.println("Child 构造函数");
    }
}

// 创建对象
Child obj = new Child();

输出顺序:

Parent 实例块
Parent 构造函数
Child 实例块
Child 构造函数

内存初始化过程:

  1. 分配内存后,a=0, b=0(默认值)。
  2. 执行父类初始化:a=10 → 父类实例块 → 父类构造函数。
  3. 执行子类初始化:b=20 → 子类实例块 → 子类构造函数。

通过以上步骤,JVM 确保对象被正确初始化并处于有效状态,之后可通过引用操作对象。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言