在方法(在Java中)中更改对象参数是不好的做法吗?

时间:2018-08-28 14:01:17

标签: java copy mutate method-parameters

我有一个关于在方法中对方法参数(即对象)进行变异的问题。

我多次听到并听到,以参数形式传入的方法对对象进行变异是一种不好的做法。例如:

public void modifyList(List<Object> list) {
    list.add(new Object());
}

相反,应该复制传入的Object,对复制的对象执行变异,并返回复制的对象。例如:

public List<Object> getModifiedList(List<Object> list) {
    List copy = new List<Object();
    //Make a deep copy if it would be necessary
    for(Object o : list) {
        copy.add(o.clone());
    }
    //Modify the copy
    copy.add(new Object());
    //return the copy
    return copy;
}

我知道第二种方法产生副作用的可能性较小,因为它不会改变输入参数。

但这真的是要走的路吗?由于必须创建许多深层副本,因此性能会受到影响。同样,为所有类实现Copy-Constructors和实现克隆方法将花费大量时间。同样,它将增加LOC的数量。

实际上,我通常不会看到这种模式(复制方法参数)。

具有丰富经验(多年作为程序员/软件开发人员)的人可以回答吗?

问候 小牛

2 个答案:

答案 0 :(得分:2)

两种方法都很好,根据您的用例,可能是正确的选择。只需确保以清晰的意图命名它们并编写一些Javadoc。

然后由开发人员决定是否可以对原始列表进行更改,如果不行,则传递副本或使用其他方法。

例如,JDK中的this method突变了一个现有列表,但是其意图和文档非常清楚。

答案 1 :(得分:2)

正如您已经暗示的那样,这取决于您的用例。使组件不可变具有许多优点,例如更好的封装线程安全避免具有无效状态等。当然,通过这种方式实施效果提升。但是经验丰富的人为此写了一章,我只能推荐:

Effective Java-

项目50:在需要时制作防御性副本。

他建议:

  

您必须进行防御性编程,并假设班级的客户将尽最大努力销毁其不变式。

还有:

  

总而言之,如果类具有从其客户端获取或返回给其客户端的可变组件,则该类必须防御性地复制这些组件。如果复制成本过高,并且该班级信任其客户不要不适当地修改组件,则可以用概述客户不修改受影响组件责任的文档来代替防御性副本。