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

如何修复Java Date类使其实例创建后日期不可修改?

修复Date类不可变性的两种方案(最简&最优)

这个问题其实是典型的封装破坏——你把内部可变数组的直接引用返回给了外部,外部代码自然能通过这个引用修改你的内部状态,完全违背了Date实例不可修改的设计初衷。下面给你两种修复方案,按需选择:

方案1:最简快速修复——返回数组副本

只需要修改getDate()方法,返回内部数组的克隆副本,而不是原引用。这样外部拿到的是独立的新数组,修改它不会影响Date实例内部的ymd数组。

修改后的Date类代码:

public class Date {
    private int[] ymd = new int[3];
    public Date(int year, int month, int day) {
        ymd[0] = year;
        ymd[1] = month;
        ymd[2] = day;
    }
    // 核心修改:返回数组的克隆副本
    public int[] getDate() {
        return ymd.clone(); // 也可以用Arrays.copyOf(ymd, ymd.length)效果一致
    }
    public void printDate() {
        System.out.println(ymd[0] + "-" + ymd[1] + "-" + ymd[2]);
    }
}

运行Problem2代码后,两次输出都会是2019-6-15,因为外部修改的是副本,和Date内部的数组完全无关。

方案2:最优长期方案——拆分成员变量(更符合封装语义)

其实用数组存年、月、日本身就不太贴合Date类的语义,把成员变量拆成单独的year、month、day三个int字段,不仅能彻底避免数组引用泄露的问题,代码可读性和封装性也更好。同时可以把字段设为final,从根源上强化不可变性。

修改后的Date类代码:

public class Date {
    private final int year;
    private final int month;
    private final int day;
    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    // 提供单独的语义化getter
    public int getYear() {
        return year;
    }
    public int getMonth() {
        return month;
    }
    public int getDay() {
        return day;
    }
    // 如果需要保留getDate方法,依然返回新数组
    public int[] getDate() {
        return new int[]{year, month, day};
    }
    public void printDate() {
        System.out.println(year + "-" + month + "-" + day);
    }
}

这种方案下,Date实例的字段一旦初始化就无法修改,完全保证了不可变性,同时代码更清晰易维护,是长期来看的最优选择。

方案对比

  • 方案1是临时快速修复,只改一行代码就能解决当前问题;
  • 方案2是合理的架构优化,符合面向对象封装原则,彻底杜绝类似问题,适合作为长期的代码设计。

内容的提问来源于stack exchange,提问作者Calle654

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 14:57:30