
Java多层继承下方法重写容易失效?看super调用链是否被意外截断
Java里不是写了@Override就一定走得到子类逻辑——尤其在三层及以上继承(比如A → B → C)中,如果B没显式调用super.method(),C的重写就会被跳过。
- 检查每层父类方法体:有没有漏掉
super.xxx(),特别是模板方法模式中常见的钩子方法 - 避免在中间类
B里直接return或抛异常而不委托,这会切断向下的调用流 - 用IDE的“Find Usages”查
method()所有实现,确认调用栈是否真能触达最末子类 - 调试时在各层方法首行打条件断点,观察
this.getClass()实际类型,比看声明类型更可靠
抽象类与接口混用时,default方法和abstract方法冲突怎么判?
当一个类同时继承抽象类又实现接口,且两者都有同签名方法时,Java按“类优先于接口”规则解决,但前提是抽象类提供了具体实现;如果抽象类只声明abstract,而接口有default,那子类仍必须自己实现。
- 抽象类里的
abstract void run();+ 接口里的default void run() { ... }≠ 自动继承接口默认行为 - 只有抽象类中是
void run() { ... }(非abstract),子类才无需重写,此时接口default被忽略 - 编译错误
error: types A and B are incompatible; both define run(), but with different return types说明签名不一致,别硬加@Override - 用
javap -s反编译看字节码,能清楚看到哪个方法被真正绑定到invokevirtual
类图里箭头分不清extends、implements、组合和依赖?从字节码反推最准
画类图时凭IDE提示或源码缩进容易误判关系,比如把字段类型为接口的当成实现关系,其实只是依赖;真正可靠的依据是.class文件里的super_class和interfaces常量池项。
-
javap -verbose MyClass输出中:super_class对应唯一父类(java/lang/Object也算),interfaces列出所有implements的接口 - 字段类型、方法参数、局部变量类型,都属于
dependencies,不是继承/实现关系,类图该用虚线箭头+>标注 - 内部类编译后生成独立
$类,其super_class仍是Object,不能仅凭嵌套结构判断父子继承 - Spring等框架代理类会动态生成,不在源码中体现,类图若包含它们,需单独注明“运行时生成”
为什么getClass().getSuperclass()返回null却不是Object?
这是个经典陷阱:Object.class.getSuperclass() == null,不是因为没父类,而是JVM规范规定Object的super_class索引为0,映射为空。所以不能靠getSuperclass() == null来判断是否到顶,得用== Object.class。
立即学习“Java免费学习笔记(深入)”;
- 正确终止条件是:
clazz == Object.class,而不是clazz.getSuperclass() == null - 数组类如
int[].class.getSuperclass()返回Object.class,但int[].class.isInterface()为false,它既不是普通类也不是接口 - 泛型擦除后,
List<string>.class</string>和List<integer>.class</integer>是同一个Class对象,别指望靠getClass()区分泛型参数 - 模块系统下,跨模块的类可能无法通过
Class.forName()加载,ClassNotFoundException不代表类不存在,可能是模块未导出
继承体系越深,越要警惕“看起来应该走这里,其实根本没进来”的情况。别信注释,别信命名,抓字节码和运行时this.getClass()才是底线。










