高内聚java实体类核心是数据与行为统一、语义清晰、状态可控:用boolean而非boolean防null误判,bigdecimal防浮点误差,instant表时点,枚举限合法值;校验逻辑内聚于setter/方法,构造器或builder确保完整性,隔离序列化与持久化细节。

高内聚的Java实体类,核心是让数据和行为自然统一、语义清晰、状态可控;防止强转带来的业务歧义,关键在于类型选择从源头杜绝“用错”可能——不是靠程序员记住规则,而是靠编译器和IDE帮你拦住。
字段类型必须匹配业务语义,不为省事牺牲表达力
基本类型(int、boolean)在实体类中几乎总是错误选择。它们无法表达“未知”“未设置”“数据库NULL”等真实业务状态,强行使用会导致逻辑漏洞或静默错误。
- 用户是否激活?用 Boolean isActive,而非 boolean isActive —— 否则数据库里存的是 NULL,反序列化后变成 false,系统误判为“已禁用”
- 订单金额?必须用 BigDecimal amount,不用 double 或 float —— 避免浮点误差导致对账偏差
- 创建时间?用 Instant createTime,而非 Date 或 long —— 明确时区无关、不可变、语义即“时间点”
- 状态码?优先用枚举(OrderStatus status),而非 String 或 Integer —— 把合法取值收拢到类型系统里,避免传入 "PENDING1" 这类错别字
把校验和约束逻辑封装进字段访问器,而不是甩给Service
实体类不该是纯数据容器。只要逻辑属于该对象自身不变量或生命周期规则,就该由它自己负责。
- 邮箱格式校验写在 setEmail(String email) 里:检查非空、格式合规,否则抛 IllegalArgumentException
- 金额不能为负?在 setAmount(BigDecimal amount) 中校验:Objects.requireNonNull(amount).compareTo(BigDecimal.ZERO)
- 状态变更需满足前置条件?比如订单只能从 DRAFT → CONFIRMED,就在 confirm() 方法里判断当前状态,而不是让外部反复 if-check
这样做的好处是:所有创建或修改对象的路径,都强制走同一套规则;测试时只需 new 实体 + set 属性,就能触发校验,无需 mock 整个 service 层。
构造方式要体现对象完整性,拒绝半成品状态
一个实体一旦被构造出来,就应处于可安全使用的状态。避免提供只设部分字段的构造器,或允许字段长期为 null。
- 必须提供无参构造器(ORM/JSON 框架需要),但仅用于框架反射;业务代码应通过全参构造器或 Builder 创建
- 字段超过 4 个时,用静态内部 Builder 类,把必填项设为构造参数,选填项用链式方法
- 不要在 setter 里做远程调用、DB 查询或发消息——这些属于协作行为,应由上层服务协调,实体只管“我是什么”,不管“我要通知谁”
序列化与持久化细节隔离,避免类型污染
实体类常被跨层复用(如 DB 映射、HTTP 响应、缓存序列化),不同场景对字段要求不同。直接暴露 JPA 注解或 Jackson 配置,会把技术细节混进业务模型。
- 数据库主键字段加 @Id 可以,但不要加 @JsonIgnore 或 @Transient —— 这些是传输层关注的事,应由 DTO 或专门的响应类承担
- 若需忽略某个字段(如密码),应在 Controller 层返回 ResponseDTO,而不是给实体加注解“让它别序列化”
- 实现 Serializable 并显式定义 serialVersionUID = 1L —— 防止未来字段增减导致反序列化失败
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











