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

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

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的构造方法,然后才会给给自的成员变量显示初始化,然后构造方法初始化.

http://www.xdnf.cn/news/5759.html

相关文章:

  • 生活破破烂烂,AI 缝缝补补(附提示词)
  • 进程间的通信
  • python-75-Nacos技术之Python+Nacos实现微服务架构
  • 打破效率枷锁,数企云外呼一骑绝尘
  • beyond compare 免密钥进入使用(删除注册表)
  • MacOS 上构建 gem5
  • 排错-harbor-db容器异常重启
  • PCB抄板过程、抄板软件介绍
  • 基于Qt6 + MuPDF在 Arm IMX6ULL运行的PDF浏览器(项目推介)
  • 做为一个平台,给第三方提供接口的时候,除了要求让他们申请 appId 和 AppSecret 之外,还应当有哪些安全选项,要过等保3级
  • BUUCTF Pwn hitcontraining_uaf WP
  • 学习黑客5分钟深入浅出理解系列之Windows注册表
  • Odoo 18 安全组与访问权限管理指南
  • SQLite 数据库常见问题及解决方法
  • 一般纯软工程学习路径
  • 使用达梦数据库官方管理工具SQLark导入与导出数据库表
  • 解决IDEA无法运行git的问题
  • CVE-2020-1957 漏洞报告
  • 基于MCP的智能体架构设计:实现智能体与外部世界的无缝连接
  • 辣椒青椒幼苗和杂草检测数据集VOC+YOLO格式706张2类别
  • IP协议、以太网包头及UNIX域套接字
  • 在 Java 8 中 常用时间日期类
  • 【Linux系统】自动化构建-make/Makefile的使用
  • AI Agent开发第64课-DIFY和企业现有系统结合实现高可配置的智能零售AI Agent(上)
  • #S4U2SELF#S4U2Proxy#CVE-2021-42278/42287
  • 按指定位置或关键字批量删除工作表-Excel易用宝
  • 关系实验课--笛卡尔积
  • cURL:通过URL传输数据的命令行工具库介绍
  • 请求参数:Header 参数,Body 参数,Path 参数,Query 参数分别是什么意思,什么样的,分别通过哪个注解获取其中的信息
  • 每日算法刷题Day4 5.12:leetcode数组4道题,用时1h