多态通过父类引用调用子类重写的方法,由jvm运行时动态绑定实现;需满足继承关系、子类重写非静态非私有非final方法、父类引用指向子类对象三个前提。

多态通过父类引用调用子类方法,核心在于方法重写 + 运行时动态绑定,不是靠强制转型或特殊语法,而是由 JVM 在运行时自动决定调用哪个版本的方法。
必须满足三个前提条件
只有同时满足以下三点,父类引用才能真正执行子类的方法逻辑:
- 存在继承关系:子类 extends 父类(或实现同一接口)
- 子类重写了父类的非静态、非私有、非 final的实例方法(使用
@Override推荐) - 父类引用指向子类对象:如
Animal a = new Dog();
调用过程是运行时决定的
写法上你调用的是父类声明的方法,但实际执行哪段代码,JVM 看的是右边 new 出来的具体类型:
-
a.eat()—— 编译时检查Animal中是否有eat()方法(有就行) - 运行时发现
a实际指向Dog对象,且Dog重写了eat(),就执行Dog版本 - 如果
Dog没重写eat(),则执行从Animal继承来的方法
哪些情况不会触发多态
容易误以为“用了父类引用就能调子类任意方法”,其实有明确限制:
-
属性访问不具多态性:即使子类定义了同名字段,
a.name取的是Animal类里的值 -
静态方法不具多态性:
a.staticMethod()总是调用Animal的静态方法,和实际对象无关 -
子类独有方法无法通过父类引用调用:比如
Dog有bark(),但Animal a = new Dog()后,a.bark()编译报错
一个典型例子帮你理清
假设:
class Animal {
String name = "animal";
void speak() { System.out.println("Animal speaks"); }
static void info() { System.out.println("Animal info"); }
}
class Dog extends Animal {
String name = "dog";
@Override void speak() { System.out.println("Woof!"); }
static void info() { System.out.println("Dog info"); }
void bark() { System.out.println("Dog barks loudly"); }
}
执行:
Animal a = new Dog(); a.speak(); // 输出 Woof! → 多态生效 a.info(); // 输出 Animal info → 静态方法不看对象类型 System.out.println(a.name); // 输出 animal → 字段不具多态 // a.bark(); // 编译错误 → 父类引用看不到子类新增方法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











