好的 - 标题没有多大意义。我提前道歉 - 我对一些 Java 概念比较陌生:
我有一个类,看起来有点像这样(简化):
public class SomeContainer {
T someEntity;
Map<String, Map<String, List<SomeOtherClass>>>> someCrazyMapping;
}
我有一个 SomeContainer 类型的变量,我们称之为 container1。
我想制作container2,它本质上是container1的精确副本,但我将对container2的“疯狂映射”进行一些修改。
我尝试做的是创建 container1 的“副本”,如下所示:
SomeContainer container2 = new SomeContainer(container1.getSomeEntity(), container1.getSomeCrazyMapping())
构造函数是一个 @AllArgsConstructor - 并且只是将值复制为 this.someEntity = someEntity (等)
如果我将条目放入 container2 中的“crazyMapping”中,container1 会受到影响吗?我正在运行它来检查它的行为,但如果有人能解释它是如何工作的,将不胜感激。
最佳答案
请注意,此答案是在您对构造函数的性质进行编辑之前,因此其中一些内容可能是无关紧要的,但这些概念仍然存在,因此除了补充您的情况是第四个项目符号外,我在这里没有太多要更改的地方点在下面的第一个列表中,因此可以修改 container1
通过更改 container2
确实存在,并且您需要对该映射进行浅拷贝或深拷贝,而不是存储对它的引用。
基本上,“container1
发生了什么”正是您告诉代码对 container1
执行的操作。 .幕后不会发生任何棘手的事情。
因此,无法从给出的信息中给出明确的答案,但从这一行:
SomeContainer container2 = new SomeContainer(container1.getSomeEntity(),
container1.getSomeCrazyMapping());
根据您的展示,我们能告诉您的最好的信息是
container1
只要:getSomeEntity()
的实现不修改container1
, 和 getSomeCrazyMapping()
的实现不修改container1
, 和 clear()
的方式修改您传入的参数(例如,通过在您传递它的 map 上调用 container1
或其他方式)要修改。 container1
的情况。通过 container2
稍后,例如您直接在 getSomeCrazyMapping()
中返回 map , 在 container2
中存储对它的引用,然后通过该引用对其进行修改。 我松散地使用“修改”一词,因为它实际上取决于您认为“修改”的情况,但是不,不会随机发生任何事情,您必须分析您的代码以查看您是否明确修改任何内容。
因此,为了帮助您保持对事物的谨慎控制,您可以使用一些工具。以下是一些示例,留给您作为练习,以了解如何有效地使用这些示例:
HashMap
.对相同键和值对象的引用将存储在副本中,但它至少是不同的映射。 Object#clone
你可以在你的容器、键和值对象上实现,无论如何。请注意,有些 map 实现了 Cloneable
同样,参见例如 HashMap#clone
. Collections#unmodifiableMap
可以用来包装 getSomeCrazyMapping()
的返回值如果您想以编程方式确保没有人向该方法返回的映射添加/删除值。 Map
s , 如果你坚持通用 Map
接口(interface),这可能很棘手。 public SomeContainer (SomeContainer other) {
for (ExampleEntry entry : other.getEntries())
this.addEntry(entry);
}
Fwiw,如果我的容器实现变得复杂,我可能会采用这种方法。
只是你必须在这里处理的一小部分事情。文档也是您的 friend ,清楚地记录您的不变量和假设,例如“修改此方法返回的映射将修改此容器”或“此构造函数创建其参数的深拷贝”等。然后在您的实现中坚持这些(并测试!)。
关于java - 尝试使用 Java 中的构造函数创建对象的 "copy",但是我传入的内容会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42939601/