Java TripPart类封装测试失败:如何修复隐私泄露问题?
解决TripPart类的封装泄露问题
问题核心在于Date是可变对象,你直接把外部传入的Date引用赋值给内部私有变量,导致外部和内部共享同一个对象实例。外部调用setTime()修改这个Date时,内部的start/end也会跟着变化,完全破坏了类的封装性。
要修复这个问题,必须做防御性拷贝——在构造方法、setter方法接收Date参数时,不直接复用原引用,而是创建新的Date对象;同时如果要提供getter方法,也要返回拷贝,防止外部拿到内部引用后篡改数据。
修改后的TripPart代码
import java.util.Calendar; import java.util.Date; public class TripPart{ private Date start; private Date end; public TripPart(Date date, Date date2){ // 对传入的Date做防御性拷贝 start = date != null ? new Date(date.getTime()) : null; if (date2 != null && start != null && date2.before(start)) { end = null; } else { end = date2 != null ? new Date(date2.getTime()) : null; } } public TripPart(){ start = new Date(); Calendar newEnd = Calendar.getInstance(); newEnd.setTime(start); newEnd.add(Calendar.HOUR_OF_DAY, 1); end = newEnd.getTime(); } public TripPart(TripPart toCopy){ // 复用带参数构造方法的拷贝逻辑 this(toCopy.start, toCopy.end); } public void setStart(Date date) { if (date == null) { start = null; return; } // 先拷贝传入的Date再做判断 Date newStart = new Date(date.getTime()); if (end != null) { if (newStart.before(end)) { start = newStart; } } else { start = newStart; } } public void setEnd(Date date) { if (date == null) { end = null; return; } // 先拷贝传入的Date再做判断 Date newEnd = new Date(date.getTime()); if (start != null) { if (newEnd.after(start)) { this.end = newEnd; } } else { this.end = newEnd; } } // 补充测试需要的getter,同样做防御性拷贝 public Date getStart() { return start != null ? new Date(start.getTime()) : null; } public Date getEnd() { return end != null ? new Date(end.getTime()) : null; } }
关键修改说明
- 构造方法:不再直接赋值
start = date,而是通过new Date(date.getTime())创建独立的新对象,彻底切断外部传入对象和内部变量的关联。 - setter方法:设置start/end前先拷贝传入的Date,再进行逻辑判断,避免外部修改传入的Date影响内部状态。
- getter方法:返回内部Date的拷贝而非原引用,防止外部通过getter拿到内部对象后篡改数据。
修改完成后,测试代码中修改外部的argumentstart或dep时,TripPart内部的start/end不会受到任何影响,封装测试即可通过。
内容的提问来源于stack exchange,提问作者Setsuko
相关产品推荐
相关产品推荐

