Java中浅拷贝和深拷贝

本文详细介绍了Java中对象的浅拷贝与深拷贝的区别及实现方式,包括实现Cloneable接口与重写clone方法,并通过实例展示了如何进行深拷贝以避免对象间的相互影响。

在讲拷贝之前我们,是不是遇到这样的问题

Obj oA = new Obj();
oA.setProto("属性1");
Obj oB = new Obj();
oB = oA;
oB.setProto("属性2");

这是对象的赋值,oB经过赋值,得到的是oA地址的引用,二者无论谁改变任一属性,都会相互影响.

Java 中已经给我们提供了这样的API,无需我们遍历递归自己处理.

1.浅拷贝

就是将已知对象完整的拷贝一份给一个对象(注意:已知对象中成员变量若是对象,拷贝的是地址引用)

拷贝的深层含义是:拷一份一模一样的数据给另一个对象,当两个对象内容发生变化时,彼此不受影响(对象除外)

1.1 定义的对象实现Cloneable接口,虽然这个接口中并没有抽象方法,但是如果不实现的话,就会报错,因为super.clone()是Object的方法,可能其中用到了泛型为Cloneable的对象.

1.2 重写clone方法,因为Object中的clone方法是protect修饰的,子类不能直接使用.


public class Bean implements Cloneable{
    String name;

    public Bean(String name) {
        this.name = name;
    }

    public Object clone() {
        Bean o = null;
        try {
            o = (Bean) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }

    public String getName() {
        return name;
    }

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

使用浅克隆的调用方法:

        Bean bean = new Bean("张三");
        Bean newBean = (Bean) bean.clone();
        newBean.setName("李四");
        System.out.println(bean.getName());

结果是张三,说明bean 和newBean 中的成员变量又重新开辟了一块内存空间.

1.3 问题:如果我在Bean 中添加一个对象Person 或者List 或者数组会怎样?

你会发现,新对象中的Person 或者List 或者数组又和老对象 缠缠绵绵活的潇潇洒洒,好这就引入了深拷贝.

2.深拷贝

深拷贝就是将对象中的对象,也开辟一块内存空间并且赋值,那么要求对象也必须实现Cloneable,重写克隆方法.

并且在上层对象中调用clone 方法.代码中: o.person = (Person) person.clone();


public class Bean implements Cloneable {
    String name;
    Person person;
    public Bean(String name, Person person) {
        this.name = name;
        this.person = person;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Object clone() {
        Bean o = null;
        try {
            o = (Bean) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        o.person = (Person) person.clone();
        return o;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Person implements Cloneable{

    public String name;

    public Person(String name) {
        this.name = name;
    }


    public Object clone() {
        Person o = null;
        try {
            o = (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }

    public String getName() {
        return name;
    }

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

调用:

        Bean bean = new Bean("张三",new Person("Persion"));
        Bean newBean = (Bean) bean.clone();
        newBean.setName("李四");
        newBean.getPerson().setName("newPersion");
         
        System.out.println(bean.getName()+"===="+bean.getPerson().getName());

调用结果:张三====Persion

3.补充

若该类实现序列化接口Serializable 或者Parcelable(安卓API轻量级序列化)可以实现序列化.这个序列化不同于上面的深浅拷贝深浅拷贝指的是运行内存,序列化一般指的是外部存储.

这个就不举例了,我们想想,如果A对象序列化给B对象,A更改了属性值,B也跟着变了,是不是要哭了,显然不可能的.









,




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值