java - 尝试使用 Java 中的构造函数创建对象的 "copy",但是我传入的内容会发生什么?

标签 java constructor reference

好的 - 标题没有多大意义。我提前道歉 - 我对一些 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 中存储对它的引用,然后通过该引用对其进行修改。

  • 我松散地使用“修改”一词,因为它实际上取决于您认为“修改”的情况,但是不,不会随机发生任何事情,您必须分析您的代码以查看您是否明确修改任何内容。

    因此,为了帮助您保持对事物的谨慎控制,您可以使用一些工具。以下是一些示例,留给您作为练习,以了解如何有效地使用这些示例:
  • 大多数 map 都有浅层的“复制构造函数”,例如 HashMap .对相同键和值对象的引用将存储在副本中,但它至少是不同的映射。
  • 你有例如 Object#clone 你可以在你的容器、键和值对象上实现,无论如何。请注意,有些 map 实现了 Cloneable同样,参见例如 HashMap#clone .
  • 你有例如 Collections#unmodifiableMap 可以用来包装 getSomeCrazyMapping() 的返回值如果您想以编程方式确保没有人向该方法返回的映射添加/删除值。
  • 这里是 some techniques for deep copying generic 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/

    相关文章:

    java - C# 字符串/字符串 : Compare string like in Java (by Reference)

    C++ 类对象函数

    java - 创建数组并计算大写字母的数量并通过复制到第二个数组来删除指定的字符

    java - 如何使用 sshj java api 使用用户名和密码连接到远程计算机?

    java - 使用 'this' 作为构造函数中方法调用的参数

    java - 构造函数中的对象参数

    java - Hibernate 不对 PostgreSQL 数据库进行更改

    java - 如何找到一个元素的前 N ​​个 sibling

    Java - 如何初始化对象的参数?

    c# - 为什么这段代码会初始化一个对象,然后让另一个对象等于它?