当前位置: 首页 > news >正文

继承关系下创建对象的具体流程

public class Person {int x = initX(); // 显式初始化:调用方法 initX()public Person() {System.out.println("Parent 构造器执行, x = " + x);}int initX() {System.out.println("initX() 被调用了");return 100;}
}public class Child extends Person {int y = initY();private int initY() {return 20;}public Child() {this("张三");System.out.println("Child 构造器执行");}public Child(String name) {System.out.println("有参构造器执行");}
}

 Child的字节码文件:

// class version 65.0 (65)
// access flags 0x21: public, super
public class com/itheima/test/Child extends com/itheima/test/Person {

  // compiled from: Child.java

  // access flags 0x0: package-private field
  I y                     // 字段 y,类型 int,用于存储 initY() 方法返回的值

  // access flags 0x2: private method
  private initY()I        // 私有方法 initY,返回 int
   L0
    LINENUMBER 7 L0      // 对应源代码第 7 行
    BIPUSH 20            // 将常量 20 推入操作数栈
    IRETURN              // 返回栈顶 int 值(20)
   L1
    LOCALVARIABLE this Lcom/itheima/test/Child; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1       // 方法局部变量只有一个:this

  // access flags 0x1: public constructor
  public <init>()V       // 无参构造器
   L0
    LINENUMBER 11 L0    // 对应源代码第 11 行
    ALOAD 0             // 将 this 引用推入栈
    LDC "\u5f20\u4e09"  // 将字符串常量 "张三" 推入栈
    INVOKESPECIAL com/itheima/test/Child.<init> (Ljava/lang/String;)V
                        // 调用本类带 String 参数的构造器
   L1
    LINENUMBER 12 L1    // 对应源代码第 12 行
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "Child \u6784\u9020\u5668\u6267\u884c"  // "Child 构造器执行"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
                        // 打印日志
   L2
    LINENUMBER 13 L2    // 对应源代码第 13 行
    RETURN              // 构造器返回
   L3
    LOCALVARIABLE this Lcom/itheima/test/Child; L0 L3 0
    MAXSTACK = 2
    MAXLOCALS = 1       // this

  // access flags 0x1: public constructor with String
  public <init>(Ljava/lang/String;)V
   L0
    LINENUMBER 15 L0    // 对应源代码第 15 行
    ALOAD 0             // 将 this 推入栈
    INVOKESPECIAL com/itheima/test/Person.<init> ()V
                        // 调用父类 Person 的无参构造器
   L1
    LINENUMBER 4 L1     // 对应 Person 构造器或字段初始化前的行号标记
    ALOAD 0             // 将 this 推入栈
    ALOAD 0             // 再次将 this 推入栈
    INVOKEVIRTUAL com/itheima/test/Child.initY ()I
                        // 调用本类私有方法 initY(), 返回 20
    PUTFIELD com/itheima/test/Child.y : I
                        // 将返回值存入字段 y
   L2
    LINENUMBER 16 L2   // 对应源代码第 16 行
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "\u6709\u53c2\u6784\u9020\u5668\u6267\u884c"  // "有参构造器执行"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
                        // 打印日志
   L3
    LINENUMBER 17 L3   // 对应源代码第 17 行
    RETURN             // 构造器返回
   L4
    LOCALVARIABLE this Lcom/itheima/test/Child; L0 L4 0
    LOCALVARIABLE name Ljava/lang/String; L0 L4 1
    MAXSTACK = 2
    MAXLOCALS = 2      // this, name
}
 

Person的字节码:

// class version 65.0 (65)
// access flags 0x21: ACC_PUBLIC | ACC_SUPER
public class com/itheima/test/Person {

  // compiled from: Person.java

  // access flags 0x19: ACC_PUBLIC | ACC_FINAL | ACC_STATIC
  public final static INNERCLASS java/lang/invoke/MethodHandles$Lookup

                                                        java/lang/invoke/MethodHandles Lookup

  // access flags 0x0: package-private
  I x                     // 字段 x,类型 int,用于存储 initX() 返回的值

  // access flags 0x1: ACC_PUBLIC
  public <init>()V        // Person 类的无参构造器
   L0
    LINENUMBER 6 L0      // 对应源代码第 6 行
    ALOAD 0              // 将 this 引用压入操作数栈
    INVOKESPECIAL java/lang/Object.<init> ()V
                        // 调用父类 Object 的构造器
   L1
    LINENUMBER 4 L1      // 源代码第 4 行,准备初始化 x 字段
    ALOAD 0              // 将 this 再次压入栈
    ALOAD 0              // 将 this 再次压入栈(为后续调用 initX() 提供 this)
    INVOKEVIRTUAL com/itheima/test/Person.initX ()I
                        // 调用本类包私有方法 initX(),返回 int
    PUTFIELD com/itheima/test/Person.x : I
                        // 将 initX() 的返回值存入 this.x
   L2
    LINENUMBER 7 L2      // 源代码第 7 行,打印构造信息
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
                        // 获取 System.out
    ALOAD 0              // 将 this 压入栈,为取 x 字段做准备
    GETFIELD com/itheima/test/Person.x : I
                        // 读取 this.x 的值
    INVOKEDYNAMIC makeConcatWithConstants(I)Ljava/lang/String; [
      // 使用 invokedynamic 生成字符串连接 "Parent 构造器执行, x = {0}"
      // 第一个参数 MethodHandles.Lookup
      // 第二个参数 调用点名称
      // 第三个参数 方法类型 (I)String
      // 第四个参数 模板 "Parent 构造器执行, x = \u0001"

    ]
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
                        // 打印拼接后的字符串
   L3
    LINENUMBER 8 L3      // 源代码第 8 行,结束构造
    RETURN               // 构造器返回
   L4
    LOCALVARIABLE this Lcom/itheima/test/Person; L0 L4 0
                        // 方法局部变量表:索引0 为 this
    MAXSTACK = 2         // 最大操作数栈深度
    MAXLOCALS = 1        // 最大局部变量数量

  // access flags 0x0: package-private
  initX()I               // 包私有方法 initX,返回 int
   L0
    LINENUMBER 11 L0    // 源代码第 11 行
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
                        // 获取 System.out
    LDC "initX() 被调用了"  // 将字符串常量推入栈
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
                        // 打印日志:initX() 被调用了
   L1
    LINENUMBER 12 L1    // 源代码第 12 行
    BIPUSH 100         // 将常量 100 推入栈
    IRETURN            // 返回栈顶 int 值(100)
   L2
    LOCALVARIABLE this Lcom/itheima/test/Person; L0 L2 0
                        // 方法局部变量表:索引0 为 this
    MAXSTACK = 2        // 最大操作数栈深度
    MAXLOCALS = 1       // 最大局部变量数量
}

当new Child()的具体流程图:
 

new Child()
  └─ 为 child 对象分配内存,字段 x、y 等都置为默认值 (0)

Child() ──┬─ this("张三")
          │
          └─ Child(String name)
                └─ 调用 Person.<init>()
                      ├─ super() → 调用 Object.<init>()
                      ├─ 执行父类显式初始化:
                      │     └─ 调用 initX()
                      │         ├─ 打印 "initX() 被调用了"
                      │         └─ 返回 100
                      │     └─ PUTFIELD x = 100
                      ├─ 打印 "Parent 构造器执行, x = 100"
                      └─ 返回 Person.<init>()

                ├─ 执行子类显式初始化:
                │     └─ 调用 initY()
                │         └─ 返回 20
                │     └─ PUTFIELD y = 20
                ├─ 打印 "有参构造器执行"
                └─ 返回 Child(String)

  └─ 回到 Child():
        └─ 打印 "Child 构造器执行"

 

值得注意的是:子类会调用父类的构造方法,父类会调用Object的构造方法,然后才会给给自的成员变量显示初始化,然后构造方法初始化.

相关文章:

  • (十三)Java注解(Annotation)全面解析:从基础到高级应用
  • set常用接口及模拟实现
  • Kubernetes控制平面组件:Kubelet详解(二):核心功能层
  • Linux系统编程(八)--进程间通信
  • 邮件营销应对高退信率的策略
  • C语言| 局部变量、全局变量
  • Linux 详解inode
  • 各类大豆相关数据集大合集
  • 大模型的Lora如何训练?
  • 停车四柱液压举升机 2.0 版技术白皮书
  • Spark处理过程-转换算子和行动算子(一)
  • DocsGPT 远程命令执行漏洞复现(CVE-2025-0868)
  • C# 使用HttpClient下载文件
  • ​Spring Boot 配置文件敏感信息加密:Jasypt 实战
  • 深入了解 gmx_RRCS:计算原理、操作步骤及输出文件解析
  • 【TTS学习笔记】:语音合成领域基本术语
  • 二叉树路径总和
  • 【vue】全局组件及组件模块抽离
  • .NET 在鸿蒙系统上的适配现状
  • 1.5 连续性与导数
  • 新剧|《藏海传》定档,《折腰》《人生若如初见》今日开播
  • 《AI×SCIENCE十大前沿观察》9:合成数据和数据基础设施
  • A股高开高走:沪指涨0.82%,创指涨2.63%,超4100股收涨
  • 这些网红果蔬正在收割你的钱包,营养师:吃了个寂寞
  • 消费维权周报|上周涉手机投诉较多,涉拍照模糊、屏幕漏液等
  • 瑞士联邦主席凯勒-祖特尔、联邦副主席帕姆兰会见何立峰