多态仅在满足前提时生效,私有方法、成员变量、静态方法、final方法均不支持多态,且子类特有方法无法通过父类引用直接调用。

多态不是万能的,它只在满足特定条件时才生效。一旦绕开这些前提,看似写了多态代码,实际运行效果却和预期不符——不是报错,就是静默失效。
私有方法无法参与多态
private 方法被编译器视为 final,子类无法重写,也就谈不上运行时动态绑定。父类引用调用 private 方法时,永远执行的是父类自己的实现,与实际对象类型无关。
- 即使子类定义了同名方法,也属于全新方法,不构成重写
- 编译期就绑定到父类的 private 方法,完全跳过动态分派机制
- 容易误以为“子类覆盖了”,结果输出却是父类逻辑,造成隐蔽 bug
成员变量不支持多态行为
字段访问不走虚方法表,而是静态绑定:编译时看引用类型(左边),运行时也看引用类型(左边)。无论 new 的是哪个子类,只要声明为父类类型,访问的就是父类的字段。
- 子类中声明同名字段,只是“隐藏”而非“覆盖”,两者内存地址独立
- 想拿到子类字段值?必须显式转型或直接用子类引用访问
- 这种行为常被误认为“多态失效”,其实是设计本意——字段不具备动态性
静态方法、final 方法无法多态
static 方法属于类,不依赖实例;final 方法禁止重写。二者都绕过运行时方法查找机制,直接由编译类型决定调用目标。
- 即便子类定义了同签名 static 方法,也只是独立存在,不构成重写
- 调用 static 方法时,编译器根据引用类型(而非实际对象)确定调用哪个类的方法
- final 方法在字节码层面标记为不可覆盖,JVM 直接内联或硬编码调用路径
无法直接调用子类特有方法
多态引用只能访问父类声明过的成员。子类新增的方法,在编译期就被拦截——因为父类里根本不存在这个符号。
- 这是安全机制,不是缺陷:防止因类型擦除导致非法调用
- 需要调用子类独有功能?必须先用 instanceof 判断,再强制转型
- 盲目转型可能抛 ClassCastException,务必配合类型检查使用











