多态的核心目的是解耦和替换,使调用方不依赖具体实现类;通过继承/实现接口、重写方法、父类引用调用三要素触发JVM动态绑定,实现运行时对象类型决定行为,达成开闭原则。
Java中使用多态,核心目的就一个:让调用方不依赖具体实现类。比如你写了一个支付功能,今天用 WechatPay,明天要换成 Alipay,如果直接 new WechatPay().pay(),那每换一次就得改代码;而用多态:Payment p = new Alipay(); p.pay();,只需换右边的 new 对象,左边所有调用逻辑完全不动。
ApplicationContext.getBean(Payment.class) 返回的正是这种多态对象没有多态时,新增一种行为往往要修改已有分支逻辑(比如 if-else 判断支付类型);有了多态,新增行为只需新增一个子类并实现接口,其他地方零改动——这就是开闭原则(对扩展开放,对修改关闭)的落地。
if (type == 1) { new WechatPay().pay(); } else if (type == 2) { new Alipay().pay(); } —— 每加一种支付方式都要改这个 if 块Payment p = PaymentFactory.create(type); p.pay();,工厂内部返回具体子类,外部完全无感Payment 接口的方法签名,多态也救不了设计缺陷这不是语法教条,而是 JVM 动态绑定机制的硬性要求:
继承 或 实现接口:提供统一的类型契约,保证方法签名一致@Override 方法:告诉 JVM “这里可能有不同实现”,触发运行时查表(vtable)机制Parent p = new Child():只有通过父类引用调用,JVM 才会启用动态分派;若用 Child c = new Child() 直接调用,则是静态绑定,失去多态意义
overload)是编译期行为,属于静态多态,不涉及运行时对象类型判断当你发现自己总在写 (Alipay) p 这种向下转型,说明抽象层没设计好。多态本意是“用接口说话”,一旦需要强转,就暴露了两个问题:
ClassCastException 风险,必须配合 instanceof 检查,进一步增加冗余真正健壮的多态设计,90% 场景下不需要向下转型——如果业务确实需要差异化处理,优先考虑用访问者模式、或者把差异逻辑提到策略参数里。