封装需边界清晰、职责收敛、暴露最小接口:一、属性封装禁public字段,集合返不可变视图,敏感字段脱敏;二、行为封装方法名体现业务意图,校验内聚,异常语义化;三、构造用builder或全参构造,必填字段强制传入;四、包按业务域组织,对外仅开放api/dto,dto与entity严格分离。

封装不是加个private就完事,关键在边界清晰、职责收敛、对外暴露最小必要接口。企业级场景下,封装质量直接决定模块可测试性、可替换性和协作效率。
一、属性封装:只暴露“需要被知道”的状态
所有字段默认私有,禁止public或protected成员变量。非静态常量用static final,业务配置类可配合@ConfigurationProperties绑定,不裸露原始字段。
- 避免 getter/setter 泛滥:只提供真正需要读写的方法,比如
getBalance()可以,但setBalanceDirectly()应禁用;余额变更必须走deposit()或withdraw()等带校验的业务方法 - 集合类返回不可变视图:
return Collections.unmodifiableList(items);,防止外部误修改内部状态 - 敏感字段(如密码、token)在 getter 中主动脱敏或返回
null,日志中也需屏蔽
二、行为封装:把“怎么做”藏进方法体内
方法名体现业务意图,而非技术动作。一个方法只做一件事,且该事必须属于当前类的职责范畴。
- 拒绝“工具方法”入侵业务类:比如
User类里不应出现formatPhone(String),应交由PhoneNumberFormatter处理 - 校验逻辑内聚:创建订单时,地址合法性、库存充足性、用户状态等检查都应在
OrderService.createOrder()内部完成,不依赖调用方预判 - 异常封装为业务语义:抛出
InsufficientStockException而非RuntimeException,上层无需解析错误码就能理解失败原因
三、构造与初始化:控制对象诞生的唯一入口
禁止无参构造+大量 setter 赋值。推荐使用 Builder 模式或全参数构造器,确保对象创建即处于有效状态。
- 必填字段在构造时强制传入,避免
NullPointerException延迟到运行时才暴露 - 复杂初始化逻辑(如加载缓存、校验远程依赖)放在
@PostConstruct或私有init()中,不暴露给外部 - 工厂类(如
OrderFactory)统一管理对象构建策略,应对不同来源(DB、MQ、API)的数据组装差异
四、包与模块封装:从代码组织上划清界限
包名体现业务域而非技术分层,如com.company.order下包含model、service、repository子包,而非按controller/service/dao横向切分。
- 对外仅开放
api和dto包,其他实现包加internal后缀(如order.internal),Maven/Gradle 中设为implementation而非api - 使用模块化(Java 9+ Module System)或 Spring 的
@ConditionalOnMissingBean机制,让核心模块不强依赖具体实现 - DTO 与 Entity 严格分离,禁止在 Controller 层直接返回 JPA Entity,避免序列化泄露数据库结构或触发懒加载异常
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











