java多态要求父类或接口引用指向子类对象,编译看引用类型、运行看实际类型;仅非static、非private、非final且被重写的方法参与多态;字段访问无多态性。

Java 中多态通过父类(或接口)引用调用具体实现,核心在于“编译看左边,运行看右边”——编译时检查引用类型是否具备该方法,运行时由实际对象类型决定执行哪个方法体。
接口/父类引用指向子类对象
这是多态的前提。必须用接口类型或父类类型声明变量,但用子类(或实现类)实例初始化:
-
正确示例(多态成立):
Animal a = new Dog();或List<string> list = new ArrayList();</string> -
错误示例(无多态):
Dog d = new Dog();—— 编译和运行都绑定到 Dog,不涉及动态分派
方法必须是可重写(override)的实例方法
只有满足以下条件的方法才能体现多态行为:
- 非 static(静态方法绑定在编译期,属类级别,不参与多态)
- 非 private(无法被重写)
- 非 final(不能被重写)
- 子类中确实重写了该方法(签名一致,且不是重载)
例如:a.speak() 调用的是 Dog.speak() 还是 Cat.speak(),取决于 a 实际指向的对象,而非声明类型 Animal。
接口方式调用更常见且推荐
面向接口编程是多态的最佳实践。接口定义契约,实现类提供行为:
- 定义接口:
interface Payment { void pay(double amount); } - 多个实现:
class Alipay implements Payment { public void pay(double a) { ... } }、class WechatPay implements Payment { public void pay(double a) { ... } } - 运行时注入:
Payment p = useAlipay ? new Alipay() : new WechatPay(); p.pay(100.0);
这样新增支付方式(如 ApplePay)无需修改调用方代码,符合开闭原则。
注意:属性访问不具多态性
字段(成员变量)不支持多态。如果父类和子类有同名字段,访问的是引用类型声明的字段:
-
class Animal { String type = "Animal"; }class Dog extends Animal { String type = "Dog"; } Animal a = new Dog(); System.out.println(a.type); // 输出 "Animal"
想获得子类特有状态,应通过 getter 方法(而 getter 可被重写,从而体现多态)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











