Java封装防非法修改的核心是编译器强制拦截private字段+setter校验双保险:private切断直连路径,setter嵌入业务规则,不可变对象返回副本或只读视图,final锁定关键常量。

Java 封装防止外部非法修改数据,核心不是靠“提醒”或“约定”,而是用编译器强制拦截 + 方法层逻辑控制双保险。关键在于切断直连路径,并把所有写入操作收归到可控入口。
用 private 彻底封死字段直读直写
private 是第一道物理防线。它不是运行时检查,而是在编译阶段就报错:
- 哪怕同包、子类、甚至反射(需显式权限且可被 SecurityManager 拦截),都无法直接写 obj.age = -5 或读 int x = obj.balance
- 编译器直接拒绝:error: private access 或 error: cannot find symbol
- 这意味着——没有 getter/setter 的话,外部连“看一眼”都不行,更别说改
在 setter 中嵌入校验逻辑
字段私有化后,所有修改必须走 public void setXxx() 方法。这里就是加守门规则的地方:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 年龄不能为负或超 150:if (age < 0 || age > 150) throw new IllegalArgumentException("年龄非法");
- 密码长度不得少于 6 位,且不能含空格:if (pwd == null || pwd.length() < 6 || pwd.contains(" "))
- 余额变动必须是非负数,且不能导致透支:if (amount < 0 || this.balance + amount < 0)
防住可变对象的“软篡改”
即使字段是 private,如果 getter 直接返回 List、Map、数组等可变引用,外部仍能绕过 setter 修改内部状态:
立即学习“Java免费学习笔记(深入)”;
- 错误写法:public List<String> getTags() { return tags; } → 外部调用 list.add("new") 就破坏了封装
- 正确做法:return Collections.unmodifiableList(tags); 或 return new ArrayList<>(tags);
- 对数组用 Arrays.copyOf(arr, arr.length);对 Map 用 new HashMap<>(map)
用 final 锁定不可变字段
对创建后绝不该变的数据(如 ID、创建时间、配置常量),用 final + private 组合加固:
- private final String userId; —— 构造器里必须初始化,之后无法重赋值
- private final LocalDateTime createdAt = LocalDateTime.now();
- final 不仅防修改,还天然支持线程安全,避免并发写冲突

















