欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 深copy 浅copy 引用copy

程序员文章站 2022-06-03 14:22:06
...

大家好,我是烤鸭:

    今天分享一下浅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;
    }
}   

结果如图:

Java 深copy 浅copy 引用copy

 

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);
    }

如图:

Java 深copy 浅copy 引用copy

可以看出,改变了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;

如图:

Java 深copy 浅copy 引用copy

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);
    }

如图:

   Java 深copy 浅copy 引用copy