核心属性必须显式 private,getter 应安全无副作用、返回不可变对象或副本,setter 需前置校验与防御性拷贝,访问器按业务语义有选择地提供。

用 private 修饰核心属性,本质是划定“谁可以碰数据”的边界;提供标准访问契约,不是机械生成 getter/setter,而是设计一套可信赖、可预期、有边界的交互规则。关键不在“有没有”,而在“怎么锁、怎么放、放多少”。
核心属性必须显式 private,不妥协
所有业务关键字段(如用户邮箱、账户余额、订单状态)都需明确加 private 修饰符,不能依赖默认包权限或设为 protected / public。这不是形式主义,而是切断非法修改的第一道闸门。
- ✅ 正确写法:
private String email;、private BigDecimal balance; - ❌ 错误写法:
String email;(同包类可随意篡改)、public int version;(外部直接递增导致状态错乱) - 常量(如
public static final int MAX_RETRY = 3;)不在此列,它不属于封装对象状态的范畴
getter 是只读出口,要安全、无副作用
getter 不是“把字段原样搬出来”,而是对外提供一个受控、可信的视图。它的职责单一:返回当前值,且不能让调用方意外影响内部状态。
- 基本类型和不可变对象(
String、LocalDate、BigDecimal)可直接返回 - 可变引用类型(如
List<string></string>、Map<k></k>)必须返回副本:return new ArrayList(this.tags);,防止外部修改破坏内部一致性 - 禁止在 getter 中做日志记录、远程调用、复杂计算——这些行为会隐式增加调用成本,违背“读操作应轻量”的契约预期
setter 是唯一入口,必须校验 + 防御性拷贝
setter 是数据进入对象的法定通道,也是校验逻辑最该发力的地方。它不是“赋个值就完事”,而是承担着守门员角色。
- 参数校验必须前置:空值检查、范围限制(如年龄 0–150)、格式验证(邮箱正则、手机号长度)
- 接收可变对象时务必防御性拷贝:
this.items = new ArrayList(items);,避免后续外部修改污染内部状态 - 避免副作用:不在 setter 内发消息、更新时间戳、联动修改其他字段——这些逻辑应由更高层协调,保持 setter 职责纯粹
按契约需要提供,不盲目成对
访问器不是装饰品,而是契约条款。提供什么、不提供什么,取决于业务语义和使用场景。
- 只读字段(如创建时间
createdAt、主键id):只暴露 getter,setter 可省略或抛UnsupportedOperationException - 只写字段(如密码重置令牌):setter 做强校验并加密存储,getter 可返回
null或直接不提供 - 计算属性(如
isAdult()):不对应真实字段,getter 内根据age动态判断,无需 setter - IDEE 自动生成的代码只是起点,必须人工审查并补上校验、副本、异常提示等关键逻辑











