跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何在Java中实现类的封装特性_Java数据安全性编程

真正封装需private字段+校验型setter+不可变副本getter:setter校验输入(如age∈(0,150)),getter返回防御性拷贝(如unmodifiableList),禁用全量set方法,因String等不可变类可public final而List等可变容器必须控制访问路径。 Java里怎么用private+getter/setter才算真正封装 封装不是加个
private
就完事,关键在“控制访问路径”。很多代码把字段设成
private
,但
setter
无脑透传、
getter
直接返回可变对象引用,等于没封。 字段必须
private
,连
protected
都不行——子类访问会绕过校验逻辑
setter
里要校验:比如
setAge(int age)
得检查
age > 0 && age < 150
,不能只做赋值
getter
返回不可变副本:如果字段是
List
,别直接return原集合,改用
new ArrayList<>(this.items)
或
Collections.unmodifiableList(this.items)
避免提供“全量修改”方法:比如不要写
setUser(User user)
,而应拆成
setName()
、
setEmail()
等带校验的单点方法 为什么String、LocalDateTime这类字段可以直接public final但List不行 因为
String
和
LocalDateTime
是不可变类(immutable),即使你把它设为
public final
,外部也无法修改其内部状态;但
List
、
Map
、数组这些可变容器,一旦暴露引用,调用方就能add/remove/clear,彻底破坏封装边界。 安全做法:
private final List tags = new ArrayList<>();
,然后只提供
addTag(String tag)
和
getTagsCopy()
错误示范:
public List getTags() { return tags; }
—— 这会让外部随意修改内部列表 注意
final
只保证引用不变,不保证对象内容不变。对可变对象,
final
只是第一道弱防线 IDE自动生成getter/setter时最常漏掉的三件事 IntelliJ或Eclipse一键生成的
getter
/
setter
默认不处理校验、深拷贝、空值防御,直接用等于埋雷。 字符串字段的
setter
没判
null
:应该写
if (name == null) throw new IllegalArgumentException("name cannot be null");
集合字段的
getter
没做防御性拷贝:生成后手动替换成
return Collections.unmodifiableList(new ArrayList<>(this.items));
数值字段没范围校验:比如
score
字段,生成的
setScore(int score)
应补上
if (score < 0 || score > 100) throw ...
当需要序列化(JSON/DB)时,封装和Jackson/Hibernate怎么共存 框架需要访问字段或调用
setter
,但又不能破坏封装逻辑——这时候别开后门,用标准机制解耦。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 立即学习 “ Java免费学习笔记(深入) ”; Jackson:用
@JsonCreator
和
@JsonProperty
标注全参构造器,让反序列化走构造路径,避开无校验的
setter
Hibernate:用
@Access(AccessType.PROPERTY)
强制它通过
getter
/
setter
访问,确保校验逻辑生效 禁止用
@JsonIgnore
屏蔽字段再另写“工具方法”:那等于在封装墙上凿洞,后续维护者根本看不出数据流从哪进哪出 如果必须用字段直访(如Lombok的
@Data
),至少加上
@Setter(AccessLevel.PRIVATE)
并手写带校验的public方法 真正的封装难点不在语法,而在每次新增一个字段时,是否条件反射地问自己:“这个值可能被谁改?改的时候有没有业务规则要 enforce?”——漏掉一次,数据就可能从那个口子开始腐烂。

相关文章