深拷贝与浅拷贝区别

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

浅拷贝:若是基本类型,则进行值拷贝;若是引用类型,则进行地址拷贝。但是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 + '\'' +
                '}';
    }
}

若有错误,还请纠正!

相关推荐
闲猫5 小时前
Spring AI 对接Deepseek ChatModel 聊天对话
java·前端·spring
自信的未来7 小时前
JSON 工具|Web Worker 工程化打包 + 语法自动修复 + 多语言代码生成实战
java·前端·json
Brookty7 小时前
【JavaEE】线程安全(一).4:写块串行保安全、CAS
java·开发语言·java-ee·多线程·线程安全
怕孤单的草丛7 小时前
缓存管理面临的主要问题
java·数据库·缓存
犀利豆10 小时前
AI in Harness(二)
java·人工智能·后端
沉静的小伙12 小时前
在微服务中使用领域事件
java·运维·微服务
程序员在囧途12 小时前
likeadmin-api API 算力超市怎么做供应商切换?统一鉴权、task_id 和 callback_url 才能稳交付
java·服务器·数据库·开放api·likeadmin-api·api算力超市
醇氧12 小时前
Spring 容器 Map 注入机制详解
java·后端·spring
ylscode12 小时前
Cloudflare Workers Cache 深度解析:边缘缓存如何重塑无服务器性能边界
java·spring·mybatis