Java 如何使下面的类不可变?
我知道我需要使日期不可变。然而,我不确定还有什么需要修改以确保类是不变的<已为类及其方法声明了code>finalJava 如何使下面的类不可变?,java,immutability,date,Java,Immutability,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>();
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; }
}
公共期末课程日志{
私人定稿;
私人最终日期;
公共期刊(第[]条目录,日期d){
版本=新树集();
对于(int i=0;i有几种不变性。如果您想要标准不变性,这意味着每个实例变量都是final
,并且没有setter。如果您想要深度不变性,那么您的类必须是不变性的,但它的所有实例变量也必须是不变性的。或者,您可以让getter只返回您的副本r实例变量(确保它们在您的类中永远不会更改)。但是,这会带来不小的性能成本,并且会在以后产生技术债务。我相信您在java.util.Date
中使用的Date
类。因此,Date在java中是可变的(不确定原因是什么).因此,您应该返回pubDate的副本
public Date getDate()
{
return pubDate.clone();
}
另外,添加了一个不可变的新类。如果您的程序不需要特别的java.util.Date
,我建议您使用该类
编辑:根据评论日期中的建议#克隆可能会导致问题,因为日期可以被细分。使用新日期(pubDate.getTime())
复制日期对象。我能给你的最好建议是使用即时(或本地日期时间或分区日期时间)代替日期
,因为即时
(以及其他java.time
类)是不可变的。日期
已过时,不应再使用。但是,如果您需要坚持此代码,则可以进行防御性复制,如下所示:
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
对象的副本,否则您可以使用getDate()返回的对象对其进行更改
。将Date
更改为Instant
。当您将任何对象传递给类时,最好将其制作一个防御性副本,这样,如果原始对象被更改,则不会影响类。当返回对象时,出于相同的原因返回副本。取决于您何时应该执行其中一项或另一项操作,或两者都取决于对象的性质f应用程序。@Thilo我知道Date现在是遗留代码,但感谢您指出它,因为我刚刚阅读了Instant的属性。我强烈建议您使用clone
方法。有关详细信息,请参阅why@lealceldeiro我同意你的观点,我们不应该在非期末课上使用克隆。谢谢你的建议。嗨,这是我想要的ad,虽然我也忘了防御性地复制构造函数。我不知道克隆,但很高兴你强调了为什么不使用它。谢谢你。@JayG,不客气:)请记住,如果答案符合你的需要,请投票(或者标记为接受)。