这个问题是关于良好的编程习惯和避免潜在的漏洞。
我读了约书亚·布洛赫(Joshua Bloch)的《有效的Java》,这是我想知道的:
为什么我应该考虑在不可变类的不可变类的getter方法中创建防御性副本?
第二:除了 私有 之外,我为什么还要 最终确定 自己的领域?这仅与性能有关(与安全无关)吗? __
我相信这种情况可以证明以下说法是正确的:
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()
方法可以打破不变性,因为客户端代码可以修改返回的对象,因此也可以修改对象Immutable
:
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
返回不可变的对象和基元是安全的(因为它们是通过值返回的)。但是,您需要制作可变对象的防御性副本,例如Date
:
public Date getDateOfBirth() {
return new Date(dateOfBirth.getTime());
}
并将集合包装在不可变的视图中(如果它们是可变的),例如,请参见Collections.unmodifiableList()
:
public List<Integer> getSomeIds() {
return Collections.unmodifiableList(someIds);
}
问题内容: 有人可以帮助我迅速了解正确使用吸气剂和吸气剂的方法。我对它的印象与说Java不一样。 这是Swift中用于存储和访问类变量的正确用法吗? 问题答案: 斯威夫特提供了更结构化的方法来和比Java。 你可以,但你应该 不会 ,写getter和setter方法就像你在你的代码一样。 相反,(如果您使用)只需声明可见性为non的属性即可(例如,在我的示例中)。这样,您班级外的呼叫者将可以查看属
问题内容: 如何制作在不可变对象中包含可变字段的可变对象的防御性副本? MutableObject没有让我设置字段的构造函数。 MutableObject的当前状态应该在Immutable Object中捕获,并且永远不要更改。 问题答案: 您需要做的是 改成: 有关说明,请参见http://www.javapractices.com/topic/TopicAction.do?Id=15
问题内容: 我在读这篇文章,了解为什么和邪恶。本文没有说过 不要 使用它们,而是告诉您以限制使用这些方法的方式进行思考,或者引用该文章: 不要要求您进行工作所需的信息;询问具有信息的对象为您完成工作。 当您需要在GUI中显示数据但没有getter方法时会发生什么?本文简要介绍了这一点,但并不完整。它提到将JComponent传递给类,但是如果您要进行GUI更改,则可能需要进行很多工作才能修复。 例
我想使用Guava的不可变类型(例如)创建传递到方法中的集合的防御性副本。我还必须能够处理输入,并将其视为空集合。 有没有更易读的东西,最好没有三元运算符?我不认为是一个很好的替代方案,因为我和这个答案有相同的推理。
问题内容: 一直试图找到实现生成Calendar对象的防御性副本的方法的最佳方法。 例如: 当检查空输入并进行复制时,我特别担心线程的交错,还是我遗漏了一些明显的东西? 问题答案: (我想现在是针对稍微不同的受众群体的…) 如果我绝对必须使用(而不是Joda Time),我会使用。您在评论中辩解说,您担心“顽皮的子类”-您打算如何在 任何 方案中解决该问题?如果您对所涉及的子类一无所知,并且不信任
问题内容: 如果我写 是只读的,但是如果我写 然后也被修改。 如果在API中表示: 返回指定集合的不可修改视图。此方法允许模块为用户提供对内部集合的“只读”访问权限。 那么,为什么如果我修改原始集合又修改了目标复制的集合? 也许我误解了含义,如果是的话,写一份防御性副本的方式是什么? 问题答案: 是的,您理解正确。这个想法是,返回的对象不能直接更改,而是可以通过其他方式更改(通过直接更改内部集