java中用父类作形参接收子类实例实现多态,需满足继承/实现关系、子类重写非私有非静态方法、形参声明为父类类型且传入子类对象,编译看父类方法,运行看实际对象类型。

Java 中利用父类作为方法形参接收各种子类实例,是实现多态最常用、最直观的方式。它的核心在于:**用统一的父类类型声明参数,实际传入任意符合继承关系的子类对象,运行时自动调用对应子类重写的方法**。
关键前提必须满足
要让这种方式生效,三个条件缺一不可:
- 存在继承关系(子类 extends 父类)或实现关系(类 implements 接口)
- 子类必须重写父类中被调用的非私有、非静态方法(如 public void eat())
- 方法形参声明为父类(或接口)类型,实参传入子类对象(例如 feed(Pet pet),传 new Dog() 或 new Cat())
典型写法与执行逻辑
以宠物喂食为例:
- 定义抽象父类 Pet,含抽象方法 eat()
- Dog 和 Cat 分别继承 Pet,各自重写 eat()
- 主人类 Master 定义方法:public void feed(Pet pet) { pet.eat(); }
- 调用时:master.feed(new Dog()); 输出“狗吃骨头”;master.feed(new Cat()); 输出“猫吃鱼”
- 注意:编译看父类是否有该方法(否则报错),运行看实际对象类型(决定执行哪个重写版本)
为什么能这样设计?好处在哪
这种写法把“操作逻辑”和“具体对象”解耦了:
- 新增子类(比如 Penguin)只需继承 Pet 并重写 eat(),无需修改 Master.feed() 方法
- 测试代码或业务层可面向父类编程,不用关心当前是哪只宠物——提升可扩展性与可维护性
- 若形参用接口(如 feed(Edible food)),还能支持跨继承体系的对象(如食物类、药品类),灵活性更强
使用时需注意的细节
看似简单,但容易踩坑:
- 父类引用无法访问子类特有成员(如 Dog 的 catchingFlyDisc()),需先用 instanceof 判断再强制转型
- 如果父类有同名字段(如 String name),向上转型后访问该字段取的是父类值,不是子类值(方法才动态绑定,字段不绑定)
- 形参为普通父类时,要求子类对象必须已创建;若为抽象类或接口,则只能传子类实例,不能直接 new 父类
- 建议对形参做非空校验(if (pet == null) throw ...),避免空指针
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











