java中getter需防御性拷贝可变对象:date/timestamp须new副本;集合用unmodifiablelist或arraylist副本;优先改用localdatetime/instant等不可变类型,避免拷贝。

Java 中 getter 方法防止返回内部引用,核心是避免把可变对象的原始引用交出去。一旦外部拿到引用,就能绕过 setter 直接修改内部状态,封装就形同虚设。
基本类型和不可变对象可直接返回
int、boolean、long、String、LocalDateTime、Instant 等类型本身不可变,getter 里 return 字段值是安全的:
-
String name; →
return name;没问题,字符串内容无法被改 -
LocalDateTime createdAt; →
return createdAt;安全,所有“修改”都返回新实例
Date 和 Timestamp 必须防御性拷贝
java.util.Date 和 java.sql.Timestamp 是可变的,直接 return 会泄露引用:
- 错误写法:
return this.date;→ 外部调用date.setTime(0)就改了你内部时间 - 正确写法:
return new Date(this.date.getTime()); - Timestamp 同理:
return new Timestamp(ts.getTime()); - 构造器里接收 Date/Timestamp 时也要拷贝:
this.date = new Date(date.getTime());
集合类要用不可变视图或副本
List、Set、Map 等容器本身可变,直接返回引用等于开放了 add/remove/clear 权限:
- 推荐用
Collections.unmodifiableList(list):轻量、不复制元素,修改时抛异常 - 需要彻底隔离时用副本:
return new ArrayList(list); - 注意:
Collections.unmodifiableList不防内部元素被改(比如 list.get(0).setName("x")),若元素本身可变,需额外考虑深拷贝或约束元素类型
优先替换为不可变类型,比拷贝更治本
防御性拷贝是补救手段,真正减少风险的方式是源头规避:
- 把
private Date start;改成private LocalDateTime start; - 把
private Timestamp ts;改成private Instant ts; - 这样 getter 可以放心
return start;,无需拷贝,语义清晰,线程安全 - java.time 类型已取代 Date,官方明确标记 Date 为 legacy
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











