java中date类型可变,直接getter返回会破坏封装性;应优先改用java.time不可变类型如localdatetime;若必须用date,getter和构造器均需防御性拷贝。

Java中Date类型是可变的,直接在getter里return this.date会把内部对象引用暴露出去,外部调用方能通过这个引用修改原始时间,破坏封装性。根本解法不是“怎么写getter”,而是避免用Date——改用java.time包的不可变类型。
优先迁移到 java.time 不可变类型
java.util.Date 已被官方标记为过时,它的所有修改方法(如 setTime、setYear)都会改变原对象状态。而 LocalDateTime、Instant、ZonedDateTime 等 java.time 类型全部不可变:任何“修改”操作都返回新实例,原对象不受影响。
- 把 private Date start; 改成 private LocalDateTime start;
- getter 直接 return start; 安全,无需拷贝
- 需要更新时间时,用 this.start = start.plusHours(1); 这类方法替换字段值,而非修改原对象
若必须保留 Date 类型,getter 要做防御性拷贝
不能 return this.date;,否则外部调用 date.setTime(...) 就会污染内部状态。正确做法是每次返回一个新副本:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- public Date getStart() { return new Date(this.start.getTime()); }
- 或更明确地:return new Date(this.start.getTime()); —— 利用 Date(long) 构造器创建独立实例
- 注意:clone() 不推荐,因 Date.clone() 仍可能引发兼容性问题,且语义不如显式构造清晰
构造器里也要同步防御
getter 防住了读取泄露,但构造器若直接接收外部 Date 并赋值,同样会引入共享引用:
- 错误写法:this.start = start; // 外部后续改 start,内部也跟着变
- 正确写法:this.start = new Date(start.getTime()); // 构造时就隔离
Timestamp 同理处理
java.sql.Timestamp 也是可变类型,和 Date 一样存在相同风险:
- 理想方案:换成 Instant 或 LocalDateTime
- 临时兼容:getter 返回 new Timestamp(ts.getTime()),构造器也做同样拷贝
- 避免使用 ts.setNanos(...) 或 ts.setTime(...) 等修改方法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










