为什么在不可变类中的getter中制作防御性副本? [英] Why make defensive copies in getters inside immutable classes?

查看:132
本文介绍了为什么在不可变类中的getter中制作防御性副本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是关于良好的编程实践和避免潜在的漏洞。

我读了Joshua Bloch的Effective Java,这就是我想知道的:

我为什么要考虑制作防御性副本我的不可变类中的getter方法中没有mutator吗?

第二种:除了 private 之外,为什么我要创建 final 字段?这只是关于性能(不是安全性)吗?

This question is about good programming practices and avoiding potential holes.
I read Joshua Bloch's Effective Java and here is what I wonder:
Why should I consider making defensive copies in getter methods in my immutable class with no mutators in it?
And second: why should I make my fields final in addition to private ? Is this only about performance (not security) ?

推荐答案

我认为这是证明这些陈述合理的情况:

I believe this is the case that justifies this statements:

public class Immutable {

    private final String name;

    private Date dateOfBirth;

    public Immutable(String name, Date dateOfBirth) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }

    public String getName() {
        return name;
    }

    public Date getDateOfBirth() {
        return dateOfBirth;
    }

}

getName ()很好,因为它也返回不可变对象。但是, getDateOfBirth()方法可能会破坏不变性,因为客户端代码可以修改返回的对象,因此将不可变对象修改为好吧:

getName() is fine as it returns immutable object as well. However the getDateOfBirth() method can break immutability because the client code can modify returned object, hence modifying the Immutable object as well:

Immutable imm = new Immutable("John", new Date());

imm.getName(); //safe
Date dateOfBirth = imm.getDateOfBirth();
//hundreds of lines later
dateOfBirth.setTime(0);  //we just modified `imm` object

返回不可变对象和基元是安全的(因为它们按价值返回)。但是你需要制作可变对象的防御性副本,例如日期

It is safe to return immutable objects and primitives (as they are returned by value). However you need to make defensive copies of mutable objects, like Date:

public Date getDateOfBirth() {
    return new Date(dateOfBirth.getTime());
}

并将集合包装在不可变视图中(如果它们是可变的),例如请参阅 收藏集.unmodifiableList()

and wrap collections in immutable views (if they are mutable), e.g. see Collections.unmodifiableList():

public List<Integer> getSomeIds() {
    return Collections.unmodifiableList(someIds);
}

这篇关于为什么在不可变类中的getter中制作防御性副本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆