简体   繁体   English

如何使以下 class 不可变?

[英]How can I make the following class immutable?

I know I need to make Date immutable.我知道我需要使Date不可变。 However, I am not sure what else needs to be amended to ensure the class is immutable.但是,我不确定还需要修改什么以确保 class 是不可变的。 final has been declared for the class and its methods. final已声明为 class 及其方法。

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; }
}   

There are several kinds of immutability.不变性有几种。 If you want standard immutability, that means every instance variable is final and there are no setters.如果你想要标准的不变性,那就意味着每个实例变量都是final的并且没有设置器。 If you want deep immutability, then your class must be immutable, but so must all of its instance variables.如果你想要深度不变性,那么你的 class 必须是不可变的,但它的所有实例变量也必须是不可变的。 Alternatively, you can have your getters only return copies of your instance variables (ensuring that they will never change within your class).或者,您可以让您的 getter 只返回实例变量的副本(确保它们永远不会在您的类中更改)。 However, this carries a not insignificant performance cost and can create technical debt later on.然而,这会带来不小的性能成本,并且会在以后产生技术债务。

I believe Date class you are using in java.util.Date .我相信您在 java.util.Date 中使用的Date java.util.Date So, Date is mutable in java (not sure what is the reason).因此,日期在 java 中是可变的(不确定是什么原因)。 So, you should return a copy of pubDate.因此,您应该返回 pubDate 的副本。

public Date getDate() 
{
 return pubDate.clone();
}

Also, A new class has added in LocalDate which is immutable.此外,在不可变的LocalDate中添加了一个新的 class。 I would suggest to use that if you your program does not require java.util.Date specifically.如果您的程序不需要java.util.Date ,我建议您使用它。

EDIT: As per the suggestion in comment Date#clone can lead to problem as Date can be sub classed.编辑:根据评论中的建议 Date#clone 可能会导致问题,因为 Date 可以被分类。 Use new Date(pubDate.getTime()) for copying the Date object.使用new Date(pubDate.getTime())复制日期 object。

The best advice I could give you is to use Instant (or LocalDateTime or ZonedDateTime ) in place of a Date because Instant (and the other java.time classes) are immutable.我能给你的最好建议是使用Instant (或LocalDateTimeZonedDateTime )代替Date因为Instant (和其他java.time类)是不可变的。 Date is obsolete and should no longer be used. Date已过时,不应再使用。 But, if you need to stick to this code then you could do defensive copies , something like the following:但是,如果您需要坚持使用此代码,那么您可以执行防御性副本,如下所示:

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

// ...

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

Notice here that the Date.clone method was not used .注意这里没有使用Date.clone方法。 This is because Date is non-final, so the clone method is not guaranteed to return an object whose class is java.util.Date , it could return an instance of an untrusted subclass that is specifically designed with malicious intentions.这是因为Date是非最终的,所以clone方法不能保证返回一个 object 其 class 是java.util.Date ,它可能返回一个不可信的子类的实例,该子类是专门为恶意设计的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM