Java 如何使一个包含日期对象的类不可变?

Java 如何使一个包含日期对象的类不可变?,java,date,immutability,Java,Date,Immutability,这只是从学术学习的角度来看。我所知道的是,每当我们想使某个类不可变时, -它必须由最终的基本字段组成 -在构造对象期间,引用不会转义 -如果使用其他对象,那么这些对象也需要是递归不可变的,或者像java.lang.String这样的API不可变类,以及其他一些详细的注意事项 但我最近遇到了一个问题,面试官问一个应聘者创建一个不可变的类,其中包含java.util.Date。我的第一印象是这是不可能的,尽管我们可以通过包含日期字符串的字符串而不是日期对象本身来解决问题 请向我澄清这一点。谢谢。我建

这只是从学术学习的角度来看。我所知道的是,每当我们想使某个类不可变时, -它必须由最终的基本字段组成 -在构造对象期间,引用不会转义 -如果使用其他对象,那么这些对象也需要是递归不可变的,或者像java.lang.String这样的API不可变类,以及其他一些详细的注意事项

但我最近遇到了一个问题,面试官问一个应聘者创建一个不可变的类,其中包含java.util.Date。我的第一印象是这是不可能的,尽管我们可以通过包含日期字符串的字符串而不是日期对象本身来解决问题


请向我澄清这一点。谢谢。

我建议在您使用的日期前后创建一个包装器类,不要提供任何设置器或任何可以实际更改值的方法

为了使它不可变,你需要考虑以下事项:

  • 您需要确保该类不能被重写,-将其设为final

  • 将所有字段设置为私有和最终字段

  • 不要提供任何更改实例变量的设置器或方法

  • 防御性地在被调用方和调用方之间复制对象

    考虑更多


  • 这里要使类不可变,最简单的方法是创建日期对象的防御副本(当它在构造参数中传递时)。那么也不要提供任何二传。像这样,类中的日期字段的引用对此类之外的代码不可见,因此不能修改日期

    参见Tom的评论,了解所需的getter特性!谢谢你的加入

    (Getter还应该返回日期字段的副本,因为日期本身是可变的,更改Getter返回的字段也会更改类的字段。)

    有关更多信息和详细信息:

    1)不要提供“setter”方法

    2) 将所有字段设置为最终字段和私有字段

    3) 不允许子类重写方法-将类声明为final

    4) 对于可变实例变量-Ex-date:在这种情况下,需要特别注意

    5) 使构造函数私有,并在工厂方法中构造实例。 工厂方法在单个位置存储对象创建逻辑

       public static MyImmutableClass createNewInstance(Integer fld1, String fld2, Date date)
    {
        return new MyImmutableClass (fld1, fld2, date);
    }
    
    6) 相反,应该返回一个新的日期对象,并将内容复制到该对象

    public Date getDateField() {
        return new Date(dateField.getTime());
    }
    

    -这里dateField是在私有构造函数中设置的字段

    字段不需要是不可变的类型,它们只是不能被修改。您的问题是什么?您在哪里看到类型为
    Date
    的字段出现问题?这取决于程序员是否将这个日期实例传递给调用类。他不是被迫这样做的,因此拥有此类字段不是问题。@BhargavModi:声明类
    final
    与它的不可变无关。@BhargavModi-否。使类成为final可以防止其他类扩展它。它与不变性无关。@BhargavModi:在说这些胡说八道之前,请……要么这样,要么返回日期的副本。为什么要麻烦用包装纸呢?只需创建一个(私有)副本,然后不修改它。非原语可变字段的防御性副本。如果需要像
    public Date getDate(){}
    这样的getter方法,那么也在其中创建一个副本:
    返回新日期(privateDate.getTime())。答案是完美的,其中包含给定的链接。。。防御性拷贝解释得很好。在实现这些东西时,我觉得更好的选择是使用字符串作为格式化日期,或者使用长变量作为epochToDate。我如何在Kotlin数据类中做到这一点?对于kotlin的普通类,答案中提到的相同方式是否有效?