浅拷贝和深拷贝

浅拷贝

浅拷贝是使用默认clone()方法得到一个成员值完全一致的类对象

拷贝对象成员赋新值修改持有的引用地址,对象成员修改引用对象实际修改内存地址

public class Copy implements Cloneable {
    private int iNum;
    public Integer INum;
    public Reference Ref;
    public String str;
 
    // getters and setters
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
 
    public static void main(String[] args) throws CloneNotSupportedException {
        test1();
        test2();
        test3();
        test4();
        test5();
    }
}

浅拷贝时在堆中生成一个新对象

可见如下两个对象的内存地址不同,source和clone引用的是不同的对象

public Copy() {}

private static void test1() throws CloneNotSupportedException {
    Copy source = new Copy();
    System.out.println(source);
    Copy clone = (Copy) source.clone();
    System.out.println(clone);
}
copy.Copy@1b6d3586
copy.Copy@4554617c

浅拷贝基本类型成员仅拷贝值

浅拷贝时,基本类型成员变量仅复制值到自己的内存空间

public Copy(int iNum) {
    this.iNum = iNum;
}

private static void test2() throws CloneNotSupportedException {
    Copy source = new Copy(1);
    Copy clone = (Copy) source.clone();
    System.out.println(source.iNum + "|" + clone.iNum);

    source.setiNum(2);
    System.out.println(source.iNum + "|" + clone.iNum);

    clone.setiNum(2);
    System.out.println(source.iNum + "|" + clone.iNum);
}
1|1
2|1
2|2

浅拷贝引用类型成员仅拷贝引用

对象中的引用类型成员在浅拷贝时,仅拷贝内存地址(即引用),若修改内存地址(即修改引用对象内容)将同时影响原对象和拷贝对象

public Copy(Reference ref) {
    Ref = ref;
}

public static void test3() throws CloneNotSupportedException {
    Reference reference = new Reference("s0");
    Copy source = new Copy(reference);
    Copy clone = (Copy) source.clone();
    System.out.println(source.Ref + "|" + clone.Ref);

    source.getRef().setString("s1");
    System.out.println(source.getRef().getString() + "|" + clone.getRef().getString());

    clone.getRef().setString("s2");
    System.out.println(source.getRef().getString() + "|" + clone.getRef().getString());
}
copy.Reference@74a14482|copy.Reference@74a14482
s1|s1
s2|s2

原对象和拷贝对象修改引用互不影响

对象中的引用类型成员发生引用修改时,实际更改的是 对象自己持有的引用内存地址,因此相互不影响

public static void test4() throws CloneNotSupportedException {
    Copy source = new Copy(new Integer(0));
    Copy clone = (Copy) source.clone();
    System.out.println(source.getINum() + "|" + clone.getINum());

    source.setINum(new Integer(1));
    System.out.println(source.getINum() + "|" + clone.getINum());

    clone.setINum(new Integer(2));
    System.out.println(source.getINum() + "|" + clone.getINum());
}
0|0
1|0
1|2

浅拷贝不可变成员对象的解释

不可变对象的修改结果是新对象,指向新引用,所以互不影响

public Copy(String str) {
    this.str = str;
}

public static void test5() throws CloneNotSupportedException {
    String s0 = new String("s0");
    Copy source = new Copy(s0);
    Copy clone = (Copy) source.clone();
    System.out.println(source.str + "|" + clone.str);

    source.setStr(s0 + "a");
    System.out.println(source.str + "|" + clone.str);

    clone.setStr(clone.getStr() + "b");
    System.out.println(source.str + "|" + clone.str);
}
s0|s0
s0a|s0
s0a|s0b

深拷贝

深拷贝是生成一个与原对象内存结构完全相同,但成员变量完全无关的新对象。意味着深拷贝的 引用类型成员均指向独立的新对象,与原引用指向地址不同

实现方法

1)额外开辟内存空间,逐项复制填写值
2)在浅拷贝基础上,递归的将所有 引用类型成员也进行clone()拷贝
3)采用 序列化方法

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

©2018-2025 Howell版权所有 备案号:冀ICP备19000576号