【发布时间】:2010-12-19 02:12:46
【问题描述】:
我有一组对象集合,我将此引用传递给方法,该方法将执行一些业务逻辑并更新对象,因此它将反映在原始对象中,因为我将它作为引用传递。现在我的问题是如何避免原始对象的这种更新。
如果涉及克隆,请告诉我上述情况我需要做什么样的克隆
谢谢
【问题讨论】:
-
不可变对象的真棒!
-
你应该重新实现 Object.clone() 方法。查看它的文档。
我有一组对象集合,我将此引用传递给方法,该方法将执行一些业务逻辑并更新对象,因此它将反映在原始对象中,因为我将它作为引用传递。现在我的问题是如何避免原始对象的这种更新。
如果涉及克隆,请告诉我上述情况我需要做什么样的克隆
谢谢
【问题讨论】:
你的情况有点棘手:
你有一个对对象的引用数组。
Java 总是传值,所以当你将数组的引用传递给方法时,数组的引用是传值的。
因此该方法具有对与调用范围相同的数组的新引用。
您的问题的答案是:如果您不希望您的更改反映在对象中,则需要复制对象。所以,通过它。
【讨论】:
如果您希望原始对象保持不变,则需要对原始对象的副本进行更改。这意味着数组的“深拷贝”,您不仅要创建具有相同对象引用的第二个数组,还要制作数组中每个对象的副本。
根据谁应该拥有更改的对象(如果有的话),您可以在调用者中创建此副本并将其传入,或者传入原始数组并让方法制作一组副本。第一个似乎更合乎逻辑,但如果不了解您的设计,就很难说。
【讨论】:
您可以使用Collections.copy(dest, src),它将对您的数组进行深层复制。
但是,由于方法中存在错误,您应该采取一些技巧:
//Assuming, that src is an array
List<Integer> src2 = Arrays.asList(src)
List<Integer> dest = new ArrayList<Integer>(src2);
Collections.copy(dest, src2);
实际上,您不必传递源数组来构造目标数组。您必须传递一个与源数组大小相同的数组。
【讨论】:
有多种方法可以停止对作为参数传递的对象进行更改的方法:
clone() 更好。当然,如果您尝试“保护”的对象具有您想要阻止更改的深层结构,那么您需要确保处理此问题;例如通过深度复制、返回组件对象的副本或将它们包装返回,等等。
上面的大多数方法都增加了复杂性和运行时成本,所以我的建议是避免设计你需要做这种事情的地方。如果可行,只需记录对象应处理为只读,并将其留给编写方法以执行正确操作的人的常识。
例如,众所周知的事实是,您不应更改用作Map 中键的对象的状态,使其值发生更改。但是,通常不采取任何措施来“强制执行”这一点;即使用可变对象作为键...而不是更改它们。
【讨论】: