You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 03:58:10