Java 深copy 浅copy 引用copy

大家好,我是烤鸭:

    今天分享一下浅copy和深copy。

1.   深copy

    什么是深copy,只复制原对象属性值,不管地址。

    说一下业务场景:

    如果我想创建一个对象,只是对原对象的某个属性值改变。普通的做法就是new 一个对象,然后setXXX,如果属性特别多的话不方便,这时候就是需要深copy。复制出来的对象属于不同的地址,改变复制对象的属性值不会影响原对象

    TestClone.java:

package com.xxx.xxx.utils;

import org.junit.Test;

import java.io.Serializable;

/**
 * Created by  on 2018/7/23
 */
public class TestClone {
    public TestClone() {
    }

    @Test
    public void testDeepCopy(){
        Person person1 = new Person();
        person1.id = "id1";
        person1.name = "name1";
        person1.sex = "sex1";
        System.out.println("复制前person:"+person1);
        Person clone = CloneUtils.clone(person1);
        System.out.println("这是深copy后的对象:"+clone);
        System.out.println("=========改变深copy后的对象属性=====================");
        clone.id = "id2";
        clone.name = "name2";
        clone.sex = "sex2";
        System.out.println("copy的对象:"+clone);
        System.out.println("复制后person:"+person1);
    }


}
class Person implements Serializable,Cloneable{
    String id;
    String name;
    String sex;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
    @Override
    public Person clone() {
        Person person = null;
        try {
            person = (Person) super.clone();
        } catch (CloneNotSupportedException ignored) {
            System.out.println(ignored.getMessage());
        }
        return person;
    }
}

CloneUtils.java:

package com.xxx.xxx.utils;

import java.io.*;

public class CloneUtils {
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj){
        T cloneObj = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(obj);
            obs.close();
            //分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);
            //返回生成的新对象
            cloneObj = (T) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
}   

结果如图:

2.   浅copy

    与深copy相对应,浅copy就是复制的对象指向了原对象的地址值。如果复制的对象属性值改变,原对象也会随之改变。

    如果是单个对象的话,用引用copy吧。

    如果是对象中还有属性是对象的话。

    Person.java 和 Man.java

    

class Person  implements Cloneable, Serializable  {
    String id;
    String name;
    String sex;
    Man man;
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Man getMan() {
        return man;
    }

    public void setMan(Man man) {
        this.man = man;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", man=" + man +
                '}';
    }

    @Override
    public Person clone() {
        Person person = null;
        try {
            person = (Person) super.clone();
        } catch (CloneNotSupportedException ignored) {
            System.out.println(ignored.getMessage());
        }
        return person;
    }
}
class Man{
    String name;
    String age;

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Man{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}
 /**
     * 浅复制
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Test
    public void testShallowCopy() throws IOException, ClassNotFoundException {
        Person person1 = new Person();
        Man man = new Man();
        man.name = "man1";
        man.age = "age1";
        person1.id = "id1";
        person1.name = "name1";
        person1.sex = "sex1";
        person1.man = man;
        System.out.println("复制前person:"+person1);
        Person clone = person1.clone();
        System.out.println("这是浅copy后的对象:"+clone);
        System.out.println("=========改变浅copy后的对象属性=====================");
        clone.id = "id2";
        clone.name = "name2";
        clone.sex = "sex2";
        clone.man.name = "man2";
        clone.man.age = "age2";
        System.out.println("copy的对象:"+clone);
        System.out.println("复制后person:"+person1);
    }

如图:

可以看出,改变了man的属性,原对象中的man属性值也改变了。这就是浅copy。

如果不想这样的话,就把man也clone。

man实现clone接口,重写clone方法:

class Man implements Cloneable{
    String name;
    String age;

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

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

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

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

修改copy方法:

        Man man2 = (Man) person1.man.clone();
        man2.name = "man2";
        man2.age = "age2";
        clone.man = man2;

如图:

3.    引用copy

  /**
     * 引用复制
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Test
    public void testQuoteCopy() throws IOException, ClassNotFoundException {
        Person person1 = new Person();
        person1.id = "id1";
        person1.name = "name1";
        person1.sex = "sex1";
        System.out.println("复制前person:"+person1);
        Person clone = person1;
        System.out.println("这是引用copy后的对象:"+clone);
        System.out.println("=========改变引用copy后的对象属性=====================");
        clone.id = "id2";
        clone.name = "name2";
        clone.sex = "sex2";
        System.out.println("copy的对象:"+clone);
        System.out.println("复制后person:"+person1);
    }

如图:

   

猜你喜欢

转载自blog.csdn.net/Angry_Mills/article/details/81019958
今日推荐