如何使以下类不可变?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使以下类不可变?相关的知识,希望对你有一定的参考价值。

我知道我需要使Date不可变。但是,我不确定是否需要修改其他内容以确保该类是不变的。已经为该类及其方法声明了final

public final class Journal 
    private final Set<Article> edition;
    private final Date pubDate;

    public Journal(Article [] contents, Date d) 
        edition = new TreeSet<Article>();
        for(int i=0; i <contents.length; i++)
        edition.add(contents[i]);

        pubDate = d;
    

    public Set<Article> getArticles() 
        return Collections.unmodifiableSortedSet(edition);
    

    public Date getDate()  return pubDate; 
   
答案

[我能给您的最佳建议是使用Instant(或LocalDateTimeZonedDateTime)代替Date,因为Instant(和其他java.time类)是不可变的。 Date已过时,不应再使用。但是,如果您需要坚持执行此代码,则可以执行防御副本,如下所示:

public Journal(Article [] contents, Date d) 
    // ...
    pubDate = new Date(d.getTime());


// ...

public Date getDate() 
    return new Date(pubDate.getTime());

这里注意Date.clone方法是未使用。这是因为Date是非最终的,因此无法保证clone方法返回其类为java.util.Date的对象,它可能会返回专门为恶意目的而设计的不受信任子类的实例。

另一答案

我相信您正在Date中使用java.util.Date类。因此,Date在Java中是可变的(不确定原因是什么)。因此,您应该返回pubDate的副本。

public Date getDate() 

 return pubDate.clone();

此外,LocalDate中添加了一个不可变的新类。如果您的程序不需要java.util.Date,则建议使用该选项。

EDIT:根据评论中的建议Date#clone可能会导致问题,因为Date可以被分类。使用new Date(pubDate.getTime())复制Date对象。

另一答案

有几种不变性。如果要实现标准不变性,则意味着每个实例变量均为final,并且没有设置器。如果要实现高度不变性,则您的类必须是不变的,但是其所有实例变量也必须不变。另外,您可以让您的getter只返回实例变量的副本(确保它们在您的类中永远不会改变)。但是,这带来不小的性能成本,并且以后可能会造成技术债务。

以上是关于如何使以下类不可变?的主要内容,如果未能解决你的问题,请参考以下文章

不可变类/对象、私有构造函数、工厂方法

如何创建一个完全不可变的树层次结构?建筑鸡和蛋

String为什么不可变?

String为什么不可变?

OCaml 中的 D 类不可变数据切片

如何使swiftui结构可变