java中多态通过方法重写(而非重载)实现,依赖继承、父类引用指向子类对象及运行时动态绑定;重载属编译时静态分派,不参与多态。

多态在 Java 中**不是通过方法重载实现的**,而是主要依靠**方法重写(Override)**,配合继承和父类引用指向子类对象来达成。重载(Overload)发生在同一个类中,属于编译时行为,不构成多态;而重写发生在子类中,是运行时多态的核心机制。
方法重写是运行时多态的基础
只有当子类重写父类的非 private、非 static、非 final 方法,并通过父类类型引用调用该方法时,JVM 才会在运行时根据实际对象类型决定执行哪个版本的方法——这就是动态绑定(Dynamic Method Dispatch),也是 Java 多态的本质体现。
- 重写要求:方法名、参数列表、返回类型(协变返回类型允许子类缩小)一致,访问权限不能更严格
- 必须有继承关系,且使用父类引用指向子类实例,例如:Animal a = new Dog(); a.speak();
- private / static / final 方法不能被重写,因此不参与多态
方法重载与多态无关,属于静态分派
重载是在**同一个类中**定义多个同名但参数列表不同的方法,编译器在编译阶段就根据**引用类型和实参类型**确定调用哪个方法,与实际对象类型无关。它不体现“同一操作作用于不同对象产生不同行为”的多态特征。
- 例如:print(String s) 和 print(int i) 是重载,调用哪个由变量声明类型和传入参数字面量决定
- 即使 Object obj = new String("hello"); print(obj);,也只看 obj 的编译时类型(Object),不会因为实际是 String 就选 String 版本
一个典型多态示例(仅靠重写,无需重载)
下面代码展示了纯正的运行时多态,没有重载参与:
class Animal { void makeSound() { System.out.println("Animal sound"); } }
class Dog extends Animal { @Override void makeSound() { System.out.println("Woof!"); } }
class Cat extends Animal { @Override void makeSound() { System.out.println("Meow!"); } }
public class Main {
public static void main(String[] args) {
Animal a1 = new Dog();
Animal a2 = new Cat();
a1.makeSound(); // 输出 Woof!
a2.makeSound(); // 输出 Meow!
}
}
这里所有调用都走的是同一个方法签名 makeSound(),但行为因实际对象不同而不同——这正是多态的价值所在。
为什么容易混淆重载与多态?
因为两者都涉及“同名方法”,但关键区别在于:
- 重写:看运行时对象类型,支持多态
- 重载:看编译时引用类型 + 参数类型,不支持多态
- 重载可能出现在重写链中(如父类有重载,子类重写其中某个),但重载本身不带来多态能力
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











