深拷贝与浅拷贝区别

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

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

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

浅拷贝的常用实现方式
循环遍历对象复制
java 复制代码
List<Student> destList1=new ArrayList<Student>(srcList.size());
for(Student student : srcList){
	destList1.add(student);
}
list构造函数复制
java 复制代码
List<Student> destList1=new ArrayList<Student>(srcList);
list.addAll()方法复制
java 复制代码
destList.addAll(srcList);
常见数据类型的浅拷贝
基本数据类型 Integer
java 复制代码
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类型
java 复制代码
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]
引用类型 对象
java 复制代码
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
java 复制代码
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();
            }
        }
    }
}
测试方法
java 复制代码
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 + '\'' +
                '}';
    }
}

若有错误,还请纠正!

相关推荐
xcl09257 小时前
幼儿托育系统开发实战:从需求分析到上线全流程指南
java·大数据·需求分析
吴声子夜歌7 小时前
ApacheCommons——commons-cli(命令行参数解析)
java·开发语言·apache
小小猪的春天7 小时前
Java 手写第一个 MCP Server:Spring AI MCP 半小时跑通
java·人工智能·spring boot·ai编程
find1star7 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
今天AI了吗8 小时前
DeepSeek Harness 深度解析:从评测架构到实战落地
java·网络·数据库·人工智能·架构·java-ee
许彰午9 小时前
27-AuthService登录链路
java·低代码·架构
泡海椒9 小时前
JQuick-Curl 性能分析:并发场景下的性能表现与调优,第三方接口调用不只要快写也要稳跑
java·开发语言·okhttp
Rain的Java大神之路10 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
自动化监测Learner10 小时前
Navicat Premium 17 中文版安装教程(2026最新版)
java·linux·数据库
那个松鼠很眼熟w10 小时前
4.Spring-Ai入门案例
java·人工智能·spring