Java中的object.clone()方法是如何工作的?

4
我正在尝试理解Object类的clone()方法的工作原理。 Object类中的注释说:“此方法执行此对象的“浅表副本”,而不是“深层副本”操作。”
以下是我对Shallow和Deep copy的理解。
浅拷贝尽可能少地复制。集合的浅拷贝是集合结构的副本,而不是元素的副本。浅拷贝意味着两个集合现在共享各自的元素。
深拷贝复制一切。集合的深拷贝是具有原始集合中所有元素的两个集合的副本。
因此,如果我克隆一个对象并修改其可变元素,则应该反映在创建克隆的第一个对象上,因为两者共享同一内存。为了测试这一点,我创建了3个类...
一个简单的POJO...
package test.clone;

import java.util.Arrays;

public class Misc implements Cloneable{
    private String value;

    public Misc(String value) {
        super();
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Misc [value=" + value + "]";
    }


    protected Misc clone() throws CloneNotSupportedException{
        return (Misc)super.clone();
    }

}

需要克隆的类。
package test.clone;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Victim implements Cloneable{
    private String name = "Renjith";
    private String[] educationList = {"EDU_1", "EDU_2", "EDU_3", "EDU_4"};
    private Misc[] miscList = {new Misc("1"), new Misc("2")};
    private List<Misc> miscList2 = new ArrayList<Misc>(Arrays.asList(miscList));

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String[] getEducationList() {
        return educationList;
    }
    public void setEducationList(String[] educationList) {
        this.educationList = educationList;
    }

    protected Victim clone() throws CloneNotSupportedException{
        return (Victim)super.clone();
    }
    public Misc[] getMiscList() {
        return miscList;
    }
    public void setMiscList(Misc[] miscList) {
        this.miscList = miscList;
    }


    public List<Misc> getMiscList2() {
        return miscList2;
    }
    public void setMiscList2(List<Misc> miscList2) {
        this.miscList2 = miscList2;
    }
    @Override
    public String toString() {
        return "Victim [name=" + name + ", educationList="
                + Arrays.toString(educationList) + ", miscList="
                + Arrays.toString(miscList) + ", miscList2=" + miscList2 + "]";
    }



}

主要类负责克隆和修改...

public class Main {

    public static void main(String[] args) throws CloneNotSupportedException {
        Victim victim = new Victim();

        System.out.println(victim);

        Victim secondVictim = victim.clone();

        String[] educationList = {"EDU_1_mod", "EDU_2_mod", "EDU_3_mod", "EDU_4_mod"};
        Misc[] miscList = {new Misc("3"), new Misc("4")};
        List<Misc> miscList2 = new ArrayList<Misc>(Arrays.asList(miscList));

        secondVictim.setEducationList(educationList);
        secondVictim.setMiscList(miscList);
        secondVictim.setMiscList2(miscList2);

        System.out.println(secondVictim);

        System.out.println(victim);
    }

}

我期望的输出如下所示:

受害者 [姓名=Renjith, 教育列表=[EDU_1, EDU_2, EDU_3, EDU_4], 杂项列表=[Misc [value=1], Misc [value=2]], 杂项列表2=[Misc [value=1], Misc [value=2]]] 受害者 [姓名=Renjith, 教育列表=[EDU_1_mod, EDU_2_mod, EDU_3_mod, EDU_4_mod], 杂项列表=[Misc [value=3], Misc [value=4]], 杂项列表2=[Misc [value=3], Misc [value=4]]] 受害者 [姓名=Renjith, 教育列表=[EDU_1, EDU_2, EDU_3, EDU_4], 杂项列表=[Misc [value=3], Misc [value=4]], 杂项列表2=[Misc [value=3], Misc [value=4]]]

但我得到的是:

受害者 [姓名=Renjith, 教育列表=[EDU_1, EDU_2, EDU_3, EDU_4], 杂项列表=[Misc [value=1], Misc [value=2]], 杂项列表2=[Misc [value=1], Misc [value=2]]] 受害者 [姓名=Renjith, 教育列表=[EDU_1_mod, EDU_2_mod, EDU_3_mod, EDU_4_mod], 杂项列表=[Misc [value=3], Misc [value=4]], 杂项列表2=[Misc [value=3], Misc [value=4]]] 受害者 [姓名=Renjith, 教育列表=[EDU_1, EDU_2, EDU_3, EDU_4], 杂项列表=[Misc [value=1], Misc [value=2]], 杂项列表2=[Misc [value=1], Misc [value=2]]]

有人能告诉我这是什么问题吗?
我已经阅读了Java中的Object.clone()的理解,但仍然无法理解...
1个回答

2
你没有修改列表/数组,而是用新的引用替换它们。尝试像这样更新你的设置器(setters):
public void setMiscList(Misc[] miscList) {
    this.miscList[0] = miscList[0];
    this.miscList[1] = miscList[1];
}

public void setMiscList2(List<Misc> miscList2) {
    this.miscList2.set(0, miscList2.get(0));
    this.miscList2.set(1, miscList2.get(1));
}

这应该修改共享对象,从而得到您期望的输出结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接