Java多态由重写(运行时多态)和重载(编译时多态)共同实现:重写要求继承关系、签名一致、满足“两同两小一大”,JVM动态绑定;重载在同一类中通过参数列表区分,编译期静态绑定。

Java 中的多态,本质是“同一调用,不同行为”,但它不是靠单一机制实现的——方法重写支撑运行时多态,方法重载支撑编译时多态。二者分工明确,缺一不可。
重写体现运行时多态:对象实际类型决定执行谁的方法
重写发生在继承关系中,子类提供与父类完全一致签名(方法名、参数列表、返回类型)的新实现。JVM 在运行时根据对象的真实类型动态选择方法版本,这才是多态最核心的能力。
- 必须满足“两同两小一大”:方法名和参数列表相同;返回类型和异常范围更小(如父类返回 Object,子类可返回 String);访问权限不能更严格(如父类 protected,子类至少也是 protected 或 public)
- private、static、final 方法不能被重写
- 典型写法带 @Override 注解,既提醒开发者,也由编译器校验是否真构成重写
- 例如:Animal a = new Dog(); a.sound(); 实际执行的是 Dog 类里的 sound(),不是 Animal 的——这就是运行时绑定
重载体现编译时多态:参数决定调用哪个方法
重载发生在同一个类(或子类继承后新增)中,多个同名方法靠参数列表区分。编译器在编译阶段就锁定了具体调用目标,不依赖对象类型,也不涉及继承关系。
- 判断依据只有一条:参数个数、类型或顺序至少有一项不同
- 返回值类型、访问修饰符、异常声明全都不参与重载判定——仅靠返回值不同会直接编译失败
- 常见于构造器多样化(new Person() / new Person("张三", 25))或工具方法适配(log(String) / log(Object) / log(String, Throwable))
- 例如:print(123) 调用 print(int),print("hello") 调用 print(String),编译时已确定,运行时不会变
两者协同才能撑起完整多态体系
真实项目里,重写和重载经常一起用,各自负责不同层次的灵活性。
- 比如一个绘图系统:Shape 类内部可重载 draw()(draw(Color)、draw(Color, int)),方便调用者按需传参
- 而 Circle 和 Rectangle 继承 Shape 后分别重写 draw(),让 shape.draw() 这一句代码在运行时画出不同图形
- 重载降低使用门槛,重写保障行为差异——一个管“怎么调”,一个管“执行谁”
别混淆的关键点
初学者容易把重写和重载当成“差不多的事”,其实它们从发生位置、绑定时机到设计目的都完全不同:
- 重载是“横向扩展”:同类里加多个入口,提升易用性
- 重写是“纵向定制”:子类替换父类逻辑,支持可插拔行为
- 没有继承也能重载;没有重写就谈不上真正的运行时多态
- 重载看参数,重写看对象实际类型——记住这个口诀,基本就不会错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











