面试官:Java 继承机制的本质是什么?(附图解)
理解类加载、方法分派与多态实现
形式:对话 + 图解 + 代码示例
场景:面试 & 源码学习
引言
面试官老王:小林,不要只说"extends 就表示继承",它的底层机理你真的懂吗?
候选人小林:咱们从 字节码布局 → 方法表查找 → 动态分派 三步拆解!
1. 对话 1:类加载阶段做了什么?
面试官:继承链在什么时候建立?
小林:在 加载 & 链接 阶段,ClassLoader 先加载父类再加载子类,Constant Pool 里记录了 super_class 索引,形成父子结构。
✔️ 对话 1
2. 对话 2:方法调用为啥能实现重写?
面试官:调用子类重写的方法,JVM 怎么知道用哪个?
小林:核心是 虚方法表(v-table)。编译器为每个实例方法分配表槽;子类若重写,就覆盖父类槽。运行时根据对象实际类型查表调用。
graph TD
A[Father v-table] -->|slot0| f()
B[Son v-table] -->|slot0 覆盖| f()
✔️ 对话 2
3. 对话 3:字段会不会被覆盖?
面试官:子类同名字段会"覆盖"父类吗?
小林:不会!字段在内存里是平铺的,父子字段各占自己偏移;只是名字冲突导致父类字段需用 super 访问。
✔️ 对话 3
4. 代码示例:虚方法表验证
class Father { void hello(){ System.out.println("father"); } }
class Son extends Father { @Override void hello(){ System.out.println("son"); } }
Father f = new Son();
f.hello(); // son
通过 javap -v Son.class 可看到 Son 的 methods 部分把 hello 标记 ACC_PUBLIC, 覆盖父类槽位。
5. 多态流程图
6. 常见陷阱
- 构造器中调用可被重写方法 → 早期调用多态失效。
static方法不走虚表,是 隐藏 而非覆盖。- 多重继承不支持,接口默认方法通过 虚拟接口表 合并。
7. 总结口诀
加载定链,虚表分派,字段平铺不覆盖;
掌握三步,继承底层没秘密!
1232

被折叠的 条评论
为什么被折叠?



