抽象类作参数强制传入其子类实例,确保多态调用抽象方法时运行时绑定具体实现,配合集合可批量处理不同子类对象,新增子类无需修改原有逻辑,符合开闭原则。

抽象类在 Java 中不能被直接实例化,但它能作为方法参数类型,承担“高层标准”的角色——定义行为契约、统一调用入口、屏蔽底层差异。这种用法不是为了传一个“空壳”,而是借其类型声明能力,让方法天然具备多态扩展性。
用抽象类作形参,强制接收子类对象
方法签名中声明抽象类为参数类型,编译器会确保传入的只能是它的具体子类实例。这相当于设了一道类型门槛,保证所有入参都满足基础能力约定(比如必须实现 eat()、move() 等抽象方法)。
-
合法写法:
void feed(Animal a),其中Animal是 abstract class -
可传入:
feed(new Dog())、feed(new Cat())、feed(new Bird()) -
禁止传入:
feed(new Animal())→ 编译报错;feed("dog")或feed(new String())→ 类型不匹配
方法内部靠抽象方法触发运行时多态
光把抽象类当参数还不够。真正发挥多态价值,是在方法体里调用它声明的抽象方法(或已实现的普通方法),让 JVM 在运行时根据实际对象类型自动绑定到对应子类的实现。
- 例如:
a.eat()看似调用的是Animal.eat(),但执行的是Dog.eat()或Cat.eat() - 如果只调用抽象类里已有的非抽象方法(如
a.getId()),那只是复用父类逻辑,没体现多态弹性 - 关键点:抽象方法是“钩子”,子类重写才是行为差异的来源
配合集合批量处理,天然支持开闭原则
把多个不同子类对象放进同一集合(如 List<animal></animal>),再遍历调用统一方法,新增子类无需修改原有逻辑。
List<animal> animals = Arrays.asList(new Dog(), new Cat(), new Duck());</animal>-
for (Animal a : animals) { a.makeSound(); }→ 自动分发到各子类版本 - 后续加
class Fish extends Animal { ... },只要实现全部抽象方法,就能直接加入列表,零侵入
注意边界:类型安全与设计初衷
抽象类作参数带来灵活性,但也隐含约束,需避免破坏抽象契约。
- 不能在方法内
new Animal(),也不能访问子类特有字段或方法(除非向下转型,但违背面向抽象的设计意图) - 传
null会导致运行时NullPointerException,建议方法开头做非空校验 - 子类若未完整实现抽象方法,编译阶段就失败——这不是缺陷,而是保障传入对象一定可用的机制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











