由于开发过程中只是对目标数据的查询使用,未对源数据进行查看。所以未曾发现操作目标数据会对源数据有影响这个问题。今天总结下深拷贝与浅拷贝的区别。

浅拷贝:若是基本类型,则进行值拷贝;若是引用类型,则进行地址拷贝。但是String类型特殊,它是不可变数据,每次数据修改,会自动创建新对象,分配新地址。

所以基本类型和String类型进行浅拷贝,后对目标数据进行修改,此时目标数据和源数据不一样。而如果是其他引用类型,则会导致目标数据和源数据内容一样。

浅拷贝的常用实现方式
循环遍历对象复制
List<Student> destList1=new ArrayList<Student>(srcList.size());
for(Student student : srcList){
	destList1.add(student);
}
list构造函数复制
List<Student> destList1=new ArrayList<Student>(srcList);
list.addAll()方法复制
destList.addAll(srcList);
常见数据类型的浅拷贝
基本数据类型 Integer
List<Integer> list1= Arrays.asList(1,2,3);
List<Integer> list2=new ArrayList<>();
list2.addAll(list1);
System.out.println("修改后...");
list2.add(4);
System.out.println(list1); //[1, 2, 3]
System.out.println(list2); //[1, 2, 3, 4]
 String类型
List<String> list3= Arrays.asList("1","2","3");
List<String> list4=new ArrayList<>();
list4.addAll(list3);
System.out.println("修改后...");
list4.add("4");
System.out.println(list3); //[1, 2, 3]
System.out.println(list4); //[1, 2, 3, 4]
 引用类型 对象
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TestCopy {
    public static void main(String[] args) {

        Student s1=new Student("张三","男");
        Student s2=new Student("李四","男");
        Student s3=new Student("王五","男");

        List<Student> srcList=new ArrayList<>();
        srcList.add(s1);
        srcList.add(s2);
        srcList.add(s3);
        List<Student> destList=new ArrayList<>();
        destList.addAll(srcList);

        System.out.println("修改后...");
        for(Student item:destList){
            if(item.getName().equals("张三")){
                item.setSex("女");
            }
        }
        System.out.println(srcList);  //[Student{name='张三', sex='女'}, Student{name='李四', sex='男'}, Student{name='王五', sex='男'}]
        System.out.println(destList); //[Student{name='张三', sex='女'}, Student{name='李四', sex='男'}, Student{name='王五', sex='男'}]
    }
}
class Student{
    String name;
    String sex;

    public Student(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    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 "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

深拷贝:存储的是内存地址,深拷贝会重新分配地址。目标数据与源数据不会一致。

深拷贝工具类 CloneUtils
package com.example.demo.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @Auther: lr
 * @Description: 深拷贝工具类
 */
public class CloneUtils {

    //深拷贝对象
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T deepCopy(T object) throws IOException, ClassNotFoundException {
        if (object == null) {
            return null;
        }
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=null;
        ObjectInputStream ois=null;
        try{
            //序列化
            oos=new ObjectOutputStream(bos);
            oos.writeObject(object);
            oos.flush();

            //反序列化
            ByteArrayInputStream bin=new ByteArrayInputStream(bos.toByteArray());
            ois=new ObjectInputStream(bin);
            return (T) ois.readObject();
        }finally {
            if(oos!=null){
                oos.close();
            }
            if(ois!=null){
                ois.close();
            }
        }
    }

    //深拷贝list<对象>集合
    @SuppressWarnings("unchecked")
    public static <T extends Serializable>  List<T>  deepCopyList(List<T> srcObj) {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            for (T obj : srcObj) {
                oos.writeObject(obj);
            }
            oos.flush();
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            List<T> deepCopiedList = new ArrayList<T>();
            for (int i = 0; i < srcObj.size(); i++) {
                deepCopiedList.add((T) ois.readObject());
            }
            return deepCopiedList;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (bos != null) bos.close();
                if (oos != null) oos.close();
                if (bis != null) bis.close();
                if (ois != null) ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
测试方法
import com.example.demo.util.CloneUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Auther: lr
 * @Description:
 */
public class TestCopy {
    public static void main(String[] args) {

        Student s1=new Student("张三","男");
        Student s2=new Student("李四","男");
        Student s3=new Student("王五","男");

        List<Student> srcList=new ArrayList<>();
        srcList.add(s1);
        srcList.add(s2);
        srcList.add(s3);
        //深拷贝
        List<Student> destList = CloneUtils.deepCopyList(srcList);

        System.out.println("修改后...");
        for(Student item:destList){
            if(item.getName().equals("张三")){
                item.setSex("女");
            }
        }
        System.out.println(srcList);  //[Student{name='张三', sex='男'}, Student{name='李四', sex='男'}, Student{name='王五', sex='男'}]
        System.out.println(destList); //[Student{name='张三', sex='女'}, Student{name='李四', sex='男'}, Student{name='王五', sex='男'}]
    }
}
class Student implements Serializable {
    String name;
    String sex;

    public Student(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    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 "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

若有错误,还请纠正!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部