private字段不能直接用public代替,因为封装旨在控制修改入口而非隐藏数据;设为public会导致非法值(如age=-5)绕过校验,引发状态不一致、NPE等问题,且校验责任被分散。

private字段为什么不能直接用public代替
因为封装不是为了“不让别人看见”,而是为了控制修改入口。一旦把age设为public,外部代码就能写user.age = -5或user.age = 2000,后续所有业务逻辑都得反复校验——这等于把校验责任甩给每个调用方,而不是集中在类内部。
常见错误现象:NullPointerException频发、状态不一致(比如name改了但fullName没同步)、单元测试难覆盖边界条件。
- 字段必须
private,这是底线,不是可选项 - 如果真需要“公开读”,靠
public的getXXX()方法,而不是放开字段 - 构造函数里也要走
setXXX()(或内联校验),避免绕过逻辑直接赋值
getter/setter命名和空值处理怎么写才不算错
Java Bean规范要求get/is/set前缀,但更关键的是语义一致性。比如isActive()比getActive()更准确;而setEmail(String email)里不做判空,等于默认允许null邮箱——这在数据库持久化或HTTP响应时大概率出NullPointerException。
使用场景:DTO传参、JSON序列化、ORM映射都依赖这些方法,它们不是摆设。
立即学习“Java免费学习笔记(深入)”;
-
boolean字段优先用isXXX(),如isActive(),否则Jackson等库可能识别失败 - 所有
setXXX()方法必须校验参数,if (email == null) throw new IllegalArgumentException("email cannot be null") - 返回集合的
getXXX()不要直接返回私有字段,用return Collections.unmodifiableList(this.roles)防外部篡改
Lombok的@Data到底能不能信
能省代码,但掩盖了封装意图。它自动生成的setXXX()是纯赋值,没有校验;生成的getXXX()直接返回引用,对List或Map类字段等于开后门。
性能影响不大,但兼容性风险明显:Spring Validation注解(如@NotNull)加在字段上时,Lombok生成的方法可能不触发校验;IDEA调试时也看不到实际执行的逻辑。
- 简单POJO且无业务校验?
@Data可以,但记得补@NonNull等注解 - 字段含集合、日期、嵌套对象?手动写
getXXX(),返回不可变视图 - 只要用了
@Builder,就别用@Data,构造逻辑和setter逻辑容易不一致
什么时候该打破getter/setter套路
当字段根本不该被外部读写时,硬加getter/setter反而破坏设计。比如一个cache字段,只在内部方法中更新,外部连“读”都不应该允许;又或者passwordHash只能被setPassword(String raw)间接设置,绝不能提供getPasswordHash()。
容易踩的坑:为“统一风格”而加无意义的getter,结果暴露了不该暴露的状态,或者让调用方误以为可以安全修改。
- 只写
private字段 + 私有初始化逻辑,不提供任何访问器 —— 合法且常见 - 用
package-private(默认访问级别)替代publicgetter,限制在模块内使用 - 如果业务上“设一次就不能改”,
setXXX()里加if (this.xxx != null) throw new IllegalStateException(...)










