多态的核心是父类引用调用子类重写方法:需继承、重写非private/static/final方法、向上转型;多态数组和参数均依赖此机制,而属性和静态方法无多态性。

核心思路是:用父类类型声明数组或方法参数,实际存入或传入子类对象,运行时自动调用各自重写的同名方法。
多态数组:用父类引用指向子类对象
声明数组时使用父类类型(如 Animal[]),但每个元素可以是任意子类实例(如 Dog、Cat)。只要子类重写了父类的某个方法(如 makeSound()),调用时就会执行对应子类的版本。
- 确保父类中该方法是 public 且被子类 @Override
- 数组本身不关心具体类型,只保证所有元素都“是”父类(满足 is-a 关系)
- 示例:Animal[] pets = {new Dog(), new Cat(), new Bird()}; → for (Animal a : pets) a.makeSound(); 会分别打印“汪汪”“喵喵”“啾啾”
多态参数:方法接收父类类型,实参传子类对象
定义方法时参数写父类类型(如 void feed(Animal a)),调用时可传入任意子类对象。JVM 在运行时根据实际对象类型决定调用哪个 feed() 实现(如果子类重写了)。
- 避免在方法内部用 instanceof 和强制转换——那是破坏多态的写法
- 如果需要差异化逻辑,应把差异封装进子类自己的方法里,让父类方法统一调用
- 例如:feed(new Dog()) 和 feed(new Cat()) 可分别触发 Dog.feed() 和 Cat.feed()
关键前提:继承 + 方法重写 + 向上转型
多态生效必须同时满足三点:
- 有明确的继承关系(子类 extends 父类 或 实现接口)
- 子类重写了父类的非 private、非 static、非 final 方法
- 变量/参数声明为父类类型,但实际引用的是子类对象(即发生了向上转型)
注意事项:属性和静态方法不具多态性
访问成员变量或调用 static 方法时,看的是引用变量的声明类型,不是实际对象类型。所以不要依赖父类变量名去读取子类特有字段;静态方法也不支持重写,只有隐藏(hide)。
- 错误示范:Animal a = new Dog(); System.out.println(a.name); → 输出父类的 name 值,不是 Dog 的
- 正确做法:把需差异化访问的数据也封装成方法(如 getName()),并在子类中重写










