Java多态要求父类引用指向子类对象,通过“编译看类型、运行看对象”实现动态分派;仅非static、非private、非final且被@Override的方法才具多态性;接口编程更优,字段无多态性,需用getter方法替代。

Java 多态通过父类(或接口)引用调用子类具体实现,核心在于“编译看类型、运行看对象”——声明用父类,实际执行靠子类。它不是语法技巧,而是解耦和扩展的设计基础。
父类引用必须指向子类对象
这是多态发生的前提。变量声明为父类类型,但用子类实例初始化:
- 正确写法:Animal a = new Dog(); 或 Payment p = new Alipay();
- 错误写法:Dog d = new Dog(); —— 编译期和运行期都绑定到 Dog,不触发动态分派
- 这种赋值叫“向上转型”,自动发生,安全且无需强制转换
只能调用可被重写的方法
只有满足以下全部条件的方法,才能体现多态行为:
- 是非 static 的实例方法(静态方法绑定在编译期,与对象无关)
- 不是 private(无法被继承和重写)
- 不是 final(禁止重写)
- 子类中确实 @Override 了该方法(签名一致,非重载)
例如 a.speak() 调用哪个版本,取决于 a 实际指向的是 Dog 还是 Cat,而非声明类型 Animal。
立即学习“Java免费学习笔记(深入)”;
接口方式更推荐,天然支持多态
面向接口编程让多态更清晰、更易维护:
- 定义统一契约:interface Logger { void log(String msg); }
- 多个实现:class FileLogger implements Logger、class ConsoleLogger implements Logger
- 运行时切换:Logger logger = useFile ? new FileLogger() : new ConsoleLogger(); logger.log("hello");
- 新增日志方式(如 DBLogger)不修改调用方代码,符合开闭原则
字段访问不具多态性,需用 getter 替代
成员变量没有动态绑定机制:
- 若 Animal 和 Dog 都有 String name 字段,Animal a = new Dog(); 中 a.name 取的是 Animal 类的 name 值
- 想获取子类特有状态,应定义 public String getName() 并在子类中重写
- 这样 getName() 就能参与多态,返回对应子类的实际值


















