java 深拷贝和浅拷贝

深拷贝和浅拷贝的问题无非就是拷贝过程中对象的属性是否指向的是同一个对象引用。

浅拷贝的特点:

一:作为基本数据类型来说,例如int ,double等8类数据类型,拷贝过程中肯定是值的传递,修改另一个对象的数值,不会影响到被拷贝对象的数值。
二:String 类型,String 类型虽然是引用类型,但是String类型的数据是存放在常量池中的,也就是无法修改的!当被拷贝的对象进行修改的时候,是把引用指向了新的地址,而不是在原来的地址上进行修改,所以不影响被拷贝的数据。
三:引用数据类型,例如一个对象,如果是浅拷贝,也就是说被拷贝对象和拷贝对象指向的是同一个引用,那么对其中一个对象进行修改,也会改变另一个对象的值。

1:话不多说,上代码~

public class Clones implements Cloneable {
    private String name;
    private int size;
    private Address address;

    public Address getAddress() {
        return address;
    }

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

    public String getName() {
        return name;
    }

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

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public Clones(String name, int size, Address address) {
        this.name = name;
        this.size = size;
        this.address = address;
    }

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

    @Override
    protected Object clone()  {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
            return null;
    }

    public static void main(String[] args) {
        Address address=new Address("没修改的地址",123456789);
        Clones clones=new Clones("没修改",123,address);
        Clones copys=(Clones)clones.clone();
        System.out.println(copys==clones);
        System.out.println(clones.getName()==copys.getName());
        System.out.println(clones.getSize()==copys.getSize());
        System.out.println(clones.getAddress()==copys.getAddress());
        System.out.println(clones.getAddress().getEmail()==copys.getAddress().getEmail());
        System.out.println(clones.getAddress().getHost()==copys.getAddress().getHost());
        clones.setName("修改了");
        clones.setSize(10000);
        address.setEmail("修改的邮箱");
        address.setHost(7758521);
        System.out.println("====================修改后======================");

        System.out.println(clones.getName());
        System.out.println(clones.getSize());
        System.out.println(clones.getAddress().toString());


        System.out.println("拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~");
        System.out.println(copys.getName());
        System.out.println(copys.getSize());
        System.out.println(copys.getAddress().toString());

===========================控制台输出结果====================================================

  /* 
            false
            true
            true
            true
            true
            true
            ====================修改后======================
            修改了
            10000
            Address{email='修改的邮箱', host=7758521}
            拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~
            没修改
            123
            Address{email='修改的邮箱', host=7758521}
*/
===================================================================================
    }
}

class Address{
    String email;
    int host;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getHost() {
        return host;
    }

    public void setHost(int host) {
        this.host = host;
    }

    public Address(String email, int host) {
        this.email = email;
        this.host = host;
    }

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

那么问题来了,怎么实现深拷贝呢,其实有两个实现深拷贝的方式,

  • 方式一: 需要为对象的每一层的每一个对象都实现Cloneable接口并重写clone方法

2:话不多说,继续上代码~


public class Clones implements Cloneable {
    private String name;
    private int size;
    private Address address;

    public Address getAddress() {
        return address;
    }

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

    public String getName() {
        return name;
    }

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

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public Clones(String name, int size, Address address) {
        this.name = name;
        this.size = size;
        this.address = address;
    }

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

    @Override
    protected Object clone()  {
        Object obj=null;
        try {
            obj= super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        //调用Address 类的clone方法进行深拷贝
        Clones clones=(Clones)obj;
        clones.address=(Address)clones.getAddress().clone();
            return obj;
    }

    public static void main(String[] args) {
        Address address=new Address("没修改的地址",123456789);
        Clones clones=new Clones("没修改",123,address);
        Clones copys=(Clones)clones.clone();
        System.out.println(copys==clones);
        System.out.println(clones.getName()==copys.getName());
        System.out.println(clones.getSize()==copys.getSize());
        System.out.println(clones.getAddress()==copys.getAddress());
        System.out.println(clones.getAddress().getEmail()==copys.getAddress().getEmail());
        System.out.println(clones.getAddress().getHost()==copys.getAddress().getHost());
        clones.setName("修改了");
        clones.setSize(10000);
        address.setEmail("修改的邮箱");
        address.setHost(7758521);
        System.out.println("====================修改后======================");

        System.out.println(clones.getName());
        System.out.println(clones.getSize());
        System.out.println(clones.getAddress().toString());


        System.out.println("拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~");
        System.out.println(copys.getName());
        System.out.println(copys.getSize());
        System.out.println(copys.getAddress().toString());


===========================控制台输出结果====================================================

  /* 
            false
            true
            true
            true
            true
            true
            ====================修改后======================
            修改了
            10000
            Address{email='修改的邮箱', host=7758521}
            拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~
            没修改
            123
            Address{email='没修改的地址', host=123456789}
*/
===================================================================================
    }
}

class Address implements Cloneable{
    String email;
    int host;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getHost() {
        return host;
    }

    public void setHost(int host) {
        this.host = host;
    }

    public Address(String email, int host) {
        this.email = email;
        this.host = host;
    }

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


    @Override
    protected Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
    
}
  • 方式二: 通过对象序列化实现深拷贝
将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。

3:话不多说,继续上代码~

public class Clones implements Serializable {
    private String name;
    private int size;
    private Address address;

    public Address getAddress() {
        return address;
    }

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

    public String getName() {
        return name;
    }

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

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public Clones(String name, int size, Address address) {
        this.name = name;
        this.size = size;
        this.address = address;
    }

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


    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Address address=new Address("没修改的地址",123456789);
        Clones clones=new Clones("没修改",123,address);
       //通过序列化方式,实现深拷贝
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(clones);
        oos.flush();
        //反序列化实现深度拷贝
        ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        Clones copys=(Clones)ois.readObject();

        System.out.println(copys==clones);
        System.out.println(clones.getName()==copys.getName());
        System.out.println(clones.getSize()==copys.getSize());
        System.out.println(clones.getAddress()==copys.getAddress());
        System.out.println(clones.getAddress().getEmail()==copys.getAddress().getEmail());
        System.out.println(clones.getAddress().getHost()==copys.getAddress().getHost());
        clones.setName("修改了");
        clones.setSize(10000);
        address.setEmail("修改的邮箱");
        address.setHost(7758521);
        System.out.println("====================修改后======================");

        System.out.println(clones.getName());
        System.out.println(clones.getSize());
        System.out.println(clones.getAddress().toString());


        System.out.println("深拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~");
        System.out.println(copys.getName());
        System.out.println(copys.getSize());
        System.out.println(copys.getAddress().toString());

===========================控制台输出结果====================================================

  /* 
           false
false
true
false
false
true
====================修改后======================
修改了
10000
Address{email='修改的邮箱', host=7758521}
深拷贝的对象~~~~~~~~~~~~~~~~~~~~~~~~
没修改
123
Address{email='没修改的地址', host=123456789}
*/
===================================================================================
    }
}

class Address implements Serializable {
    String email;
    int host;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getHost() {
        return host;
    }

    public void setHost(int host) {
        this.host = host;
    }

    public Address(String email, int host) {
        this.email = email;
        this.host = host;
    }

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



}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值