封装、继承、多态是java日常开发的实践节奏:封装重在可控暴露(如不可变集合、校验setter),继承慎用,优先组合,仅限明确is-a关系;多态依托接口与运行时绑定,配合策略模式和模板方法消除if-else。

Java 面向对象三大特性——封装、继承、多态——不是纸上概念,而是每天写业务代码时的“呼吸节奏”。真正落地的关键,不在于会不会写 extends 或 private,而在于是否用对了场景、守住了边界、留出了弹性。
封装:不是加 private 就完事,重点是“可控暴露”
真实项目里,封装常被简化为“字段 private + 自动生成 getter/setter”,但这恰恰埋下隐患:
- 直接返回可变集合(如
private List<order> orders;</order>),外部调用getOrders().add(...)就绕过校验,破坏内部一致性;正确做法是返回Collections.unmodifiableList(orders)或封装为只读视图 - setter 不做校验(比如用户年龄设为 -5 或 300),导致脏数据入库;应在
setAge()中强制判断if (age 150) - DTO/VO 类过度封装:像 Spring Boot 的 Controller 层接收的 DTO,若所有字段都配 setter,反而让非法参数轻易穿透;推荐用构造器+不可变字段,或配合
@Valid+ 自定义约束注解
继承:少用 extends,多用组合和抽象分层
企业级项目中,滥用继承是技术债高发区。典型反模式:为复用几个方法,硬拉一个“BaseService”让二十个 Service 去继承,结果改一个方法全链路抖动。
- 优先用组合替代继承:比如“订单服务需要发消息”,就注入
MessageSender接口,而不是让OrderService extends MessageService - 继承只用于明确的“is-a”关系:如
PaidOrder和RefundOrder都是Order的一种,可共用状态机、ID 生成等逻辑,此时继承合理 - 父类避免含具体实现:把公共逻辑抽到
protected final方法,把可变行为声明为abstract或default方法,留给子类决定
多态:靠接口和运行时绑定,解决分支爆炸
不用多态,业务代码容易长成一串 if-else 或 switch:支付方式判断、审批流程路由、消息模板选择……每次加一种类型就得改老代码。
- 定义策略接口:如
PaymentProcessor,不同实现类对应微信、支付宝、银行卡 - 用工厂或 Spring 的
@Qualifier注入具体实现,调用方只依赖接口,新增支付方式只需加个新类+配置,零侵入 - 结合模板方法模式:父类定义算法骨架(如“校验→扣减库存→生成订单→发MQ”),子类只重写其中某步(如“生成订单”的差异化逻辑)
三者协同:一个典型落地片段
以电商下单为例:
-
封装:订单实体
Order的status字段私有,仅提供confirm()、cancel()等带状态流转校验的方法 -
继承:
NormalOrder和VipOrder继承自AbstractOrder,共享订单号生成、基础校验,但 VIP 订单重写calculateDiscount() -
多态:下单完成触发通知,通过
NotificationService接口调用,实际由SmsNotifier、PushNotifier等实现,Spring 自动按用户偏好注入
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











