如何使以下类不可变?

问题描述 投票:3回答:3

我知道我需要使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; }
}   
java immutability java-date
3个回答
1
投票

[我能给您的最佳建议是使用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的对象,它可能会返回专门为恶意目的而设计的不受信任子类的实例。


1
投票

我相信您正在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对象。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.