java - 为什么 Hashmap 上的浅复制没有反射(reflect)

标签 java clone shallow-copy

我创建了添加了一些项目的 map 并克隆以演示浅复制。克隆后,我将一个新项目添加到旧引用中,但该项目未反射(reflect)到新引用中。

public class Test implements Cloneable {

    public static void main(String[] args) {
        HashMap<String,String> smap  = new HashMap<String,String>();
        smap.put("a1","a1");
        smap.put("a2","a2");
        smap.put("a3","a3");
        smap.put("a4","a4");

        //SHALLOW COPY 
        HashMap<String,String> cMap = (HashMap)smap.clone();
        cMap.put("b1","bb");


        smap.put("a5","55");

        System.out.println("orignal_map\t"+smap);
        System.out.println("cMap\t"+cMap);

        HashMap<String, String> scopyx = new HashMap<String, String>(smap);
        System.out.println("S_copy_x:\t"+scopyx);

    }
}

最佳答案

浅复制意味着它不适用于复制原始对象内部的对象。也就是说,如果您有一个包含集合的对象,并且克隆了该对象,则集合本身不会被复制,并且可能会在多个实例之间共享:

public class Test implements Cloneable {
    private List<String> innerList = new ArrayList<>();

    public void addBaz(String baz) {
        innerList.add(baz);
    }

    public List<String> getInnerList() {
        return innerList;
    }

    public void setInnerList(List<String> innerList) {
        this.innerList = innerList;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Test bar1 = new Test();
        bar1.addBaz("baz1");
        bar1.addBaz("baz2");
        bar1.addBaz("baz3");

        System.out.println("bar1 before cloning: " + bar1.getInnerList());

        Test cloneBar = (Test) bar1.clone();

        System.out.println("clone: " + cloneBar.getInnerList());

        bar1.addBaz("baz4");
        System.out.println("clone after adding to original: " + cloneBar.getInnerList());

        cloneBar.addBaz("cloneBaz1");
        System.out.println("bar1 after adding to clone: " + bar1.getInnerList());
    }
}

输出为:

bar1 before cloning: [baz1, baz2, baz3]
clone: [baz1, baz2, baz3]
clone after adding to original: [baz1, baz2, baz3, baz4]
bar1 after adding to clone: [baz1, baz2, baz3, baz4, cloneBaz1]

此外,如果您向 HashMap 添加了除 String 之外的其他对象,您可以看到,浅复制也在那里工作 - 原始映射和克隆映射包含共享对象,因此两个映射的内容可能会更改:

public class Test implements Cloneable {
    private String foo;

// getter/setter/toString ...

    public static void main(String[] args) {
        HashMap<String, Test> map = new HashMap<>();
        map.put("a1", new Test("a1"));
        map.put("a2", new Test("a2"));
        map.put("a3", new Test("a3"));

        System.out.println("map before cloning: " + map);

        HashMap<String, Test> cmap = (HashMap<String, Test>) map.clone();

        System.out.println("clone: " + cmap);

        map.put("b1", new Test("b1"));
        System.out.println("clone after adding to original: " + cmap);

        cmap.put("c1", new Test("c1"));
        System.out.println("original after adding to clone: " + map);

        map.get("a1").setFoo("new a1");
        System.out.println("clone after modifying object inside original: " + cmap);

        cmap.get("a2").setFoo("cloned a2");
        System.out.println("original after modifying the clone: " + map);
    }
}

输出为:

map before cloning: {a1=->a1, a2=->a2, a3=->a3}
clone: {a1=->a1, a2=->a2, a3=->a3}
clone after adding to original: {a1=->a1, a2=->a2, a3=->a3}
original after adding to clone: {a1=->a1, a2=->a2, a3=->a3, b1=->b1}
clone after modifying object inside original: {a1=->new a1, a2=->a2, a3=->a3, c1=->c1}
original after modifying the clone: {a1=->new a1, a2=->cloned a2, a3=->a3, b1=->b1}

关于java - 为什么 Hashmap 上的浅复制没有反射(reflect),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61639469/

相关文章:

java - Java 深拷贝和浅拷贝

java - 如何从代码中以编程方式删除 Liferay 6.1 中的 portlet

java - Liferay DocumentAndMedia 与 CMIS Hook

Java邮件: force "Content-Transfer-Encoding" to be "quoted-printable"

java - 如何复制 List 类型的 ArrayList 对象?

jquery - 克隆带有图像的项目,图像需要一段时间才能出现

ruby - 提供 ruby​​ 中需要深复制的最简单示例

c++ - [C++ 传值] : can the content of the original variables get modified by the called function?

java - 如何使用整数值来表示上涨或下跌?

java - 在 Java 中克隆的目的