java继承不创建多个对象,而是为子类在堆中分配一块连续内存,布局为:对象头→父类字段→子类字段;a a = new b()能安全赋值,因b对象内存起始处天然兼容a的字段视图。

Java 中继承不会增加对象数量,而是让子类对象在堆中占据一块连续内存,其中按顺序“平铺”父类字段和子类字段。对象头始终在最前,后面紧跟着从根父类(如 Object)开始逐级向下声明的非静态字段,最后是子类自己的字段。
子类对象只分配一次内存
执行 new B() 时,JVM 只在堆中分配一个对象实例,不是分别创建 A 和 B 两个对象。父类字段(如 int id)和子类字段(如 String name)被合并到同一块内存里,形成类似这样的布局:
- 对象头(Mark Word + 类指针)
- A 类的实例字段(
id) - B 类的实例字段(
name)
这种单块结构使 A a = new B() 能安全赋值——因为 a 引用的起始地址,恰好能按 A 的字段偏移规则访问其数据。
字段排列遵循继承链顺序
字段不是按源码书写顺序混排,而是严格按继承层级自上而下排列:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 先放
Object的字段(如有) - 再放直接父类(如
A)声明的非静态字段 - 最后放子类(如
B)自己声明的非静态字段
即使子类定义了与父类同名的字段(如都叫 name),它们仍各自独立占用空间,只是访问时取决于引用类型:用 A 类型引用访问的是父类字段,用 B 类型引用访问的是子类字段。
静态成员和方法不参与实例布局
所有 static 字段、静态代码块、方法签名等都不放在堆的对象实例中,而是加载到方法区(JDK 8+ 是元空间)。它们属于类本身,被该类所有实例共享。
- 构造器调用(如
super())只是初始化已存在的字段,并不触发新对象分配 - 多层继承(如
C extends B extends A)会线性扩展字段区域:[Header][A字段][B字段][C字段] - JVM 可能插入填充字节以满足内存对齐(如
long对齐到 8 字节边界),但逻辑顺序不变
变量访问靠固定偏移,不是查表
字段访问通过编译期确定的内存偏移量完成:
-
a.id访问的是对象头后第 8 字节位置(假设对象头占 8 字节) -
b.name访问的是更靠后的偏移位置(如 12 字节) - 不需要运行时查找或跳转,效率高
这也解释了为什么 Java 不支持多重继承:多个父类字段无法唯一确定排列顺序,会破坏偏移量的确定性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










