clone实现深拷贝

浅拷贝:被复制对象的所有值属性都与原来对象相同,而所有的对象引用属性仍然指向原来的对象。(只需实体类实现Cloneable重写clone方法return super.clone();即可)

深拷贝:在浅拷贝的基础上,所有引用其他对象的变量也进行了clone,并指向被复制过的新对象。

如果创建一个对象的新的副本,也就是说他们的初始状态完全一样,但以后可以改变各自的状态,而互不影响,就需要用到java中对象的复制,如原生的clone()方法。

克隆方式有很多,偶尔用一次的话,用哪种克隆方式问题都不大。一般性能要求稍高的应用场景,cglib和orika完全可以接受。


使用clone方式深拷贝

如果有一个非原生成员,如自定义类型的成员,那么就需要:
该成员实现Cloneable接口并重写Object的clone()方法(默认访问级别为protected),所以不要忘记提升为public可见
同时,修改被复制类的clone()方法,增加成员的克隆逻辑。

② 如果被复制对象不是直接继承Object,中间还有其它继承层次,每一层super类都需要实现Cloneable接口并覆盖clone()方法。与对象成员不同,继承关系中的clone不需要被复制类的clone()做多余的工作(如果没有自定义类型的对象的话)。

一句话来说,如果实现完整的深拷贝,需要被复制对象的继承链、引用链上的每一个对象都实现克隆机制


public class JavaTester {
    @Test
    public void testDeepCopy() throws Exception {
        Address address = new Address();
        address.setType("Home");
        address.setValue("北京");

        Person p1 = new Person();
        p1.setAge(31);
        p1.setName("Peter");
        p1.setAddress(address);

        Person p2 = (Person) p1.clone();
        System.out.println(p1 == p2);//false

        p2.getAddress().setType("Office");
        System.out.println("p1=" + p1);
        System.out.println("p2=" + p2);
        //p1=Person(name=Peter, age=31, address=Address(type=Home, value=北京))
        //p2=Person(name=Peter, age=31, address=Address(type=Office, value=北京))
        //若不处理,则type都为Office
    }
}

class Person implements Cloneable {
    private String name;
    private Integer age;
    private Address address;

    @Override
    public Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//第一句话就是克隆对象
        Address a = ((Person) obj).getAddress();//获取address对象,该对象目前由两个Person对象共同持有
        ((Person) obj).setAddress((Address) a.clone());//修改克隆对象的address属性,该address是由上面的address对象克隆得到的。
        return obj;//返回克隆对象

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}

class Address implements Cloneable {
    private String type;
    private String value;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getValue() {
        return value;
    }

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

    @Override
    public String toString() {
        return "Address{" +
                "type='" + type + '\'' +
                ", value='" + value + '\'' +
                '}';
    }
}

String,Integer等也是对象,但是他们是不可变类,所以值改变了也不会影响到对方。

@Test
public void testPlusInteger() throws Exception {
    Integer integer = 1;
    plusInteger(integer);
    System.out.println(integer);
}
public void plusInteger(Integer integer){
    integer = integer + 1;
}

猜你喜欢

转载自blog.csdn.net/weixin_44463178/article/details/108744252
今日推荐