实战中遇到的List的add方法【浅拷贝】和【深拷贝】问题

实战遇到问题重现:出现下面问题,怀疑是add方法浅拷贝造成的内存地址指向同一个的原因

结果:

测试类:

import com.zdft.purchase.until.ListCopyUtil;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description
 * @Author saq
 * @Date 2023/2/20 10:35
 */
public class CopyTest {

    @Test
    public void test() {
        // 获取一批id
        List<Long> ids = new ArrayList<>();
        ids.add(666L);
        ids.add(888L);

        UserInfo userInfo = new UserInfo();
        userInfo.setId(0L);
        userInfo.setName("张三");
        userInfo.setHobby("画画");

        List<UserInfo> oneResult = new ArrayList<>();
        oneResult.add(userInfo);
        oneResult.add(userInfo);
        for (int i = 0; i < ids.size(); i++) {
            Long id = ids.get(i);
            oneResult.get(i).setId(id);
        }
        System.out.println("第一种:【浅】拷贝");
        oneResult.forEach(item -> System.out.println(item));
        System.out.println("【浅】拷贝内存地址指向同一个");

        System.out.println("\n==========================================分割线==========================================\n");

        List<UserInfo> twoResult = new ArrayList<>();
        twoResult.add(userInfo);
        // 注意:对对象进行深拷贝以后
        twoResult.add(ListCopyUtil.deepCopy(userInfo));

        for (int i = 0; i < ids.size(); i++) {
            Long id = ids.get(i);
            twoResult.get(i).setId(id);
        }
        System.out.println("第二种:【深】拷贝");
        twoResult.forEach(item -> System.out.println(item));
        System.out.println("【深】拷贝内存地址重新指向一个新的");
    }
}

实体类

import java.io.Serializable;

/**
 * @Description
 * @Author saq
 * @Date 2023/2/20 10:36
 */
@Data
public class UserInfo implements Serializable {
    private Long id;
    private String name;
    private String hobby;
}

 

以下是证明:浅拷贝内存地址指向同一个,深拷贝以后指向不同的内存地址

结果:

测试类

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description 【浅拷贝】和【深拷贝】内存地址发生变化
 * @Author saq
 * @Date 2023/2/20 10:35
 */
public class CopyTest {

    @Test
    public void test() {

        UserInfo userInfo = new UserInfo();
        userInfo.setId(0L);
        userInfo.setName("张三");
        userInfo.setHobby("画画");

        List<UserInfo> oneResult = new ArrayList<>();
        oneResult.add(userInfo);
        oneResult.add(userInfo);

        System.out.println("第一种:【浅】拷贝");
        oneResult.forEach(item -> System.out.println(item));
        System.out.println("【浅】拷贝内存地址指向同一个");

        System.out.println("\n==========================================分割线==========================================\n");

        List<UserInfo> twoResult = new ArrayList<>();
        twoResult.add(userInfo);
        // 注意:对对象进行深拷贝以后
        twoResult.add(ListCopyUtil.deepCopy(userInfo));

        System.out.println("第二种:【深】拷贝");
        twoResult.forEach(item -> System.out.println(item));
        System.out.println("【深】拷贝内存地址重新指向一个新的");
    }
}

工具类

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collections;
import java.util.List;

public class ListCopyUtil {
    /**
     * 对集合进行深拷贝
     * 注意需要岁泛型类进行序列化(实现serializable)
     *
     * @param src
     * @param <T>
     * @return
     * @throws
     */
    public static <T> List<T> deepCopy(List<T> src) {
        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
             ObjectOutputStream outputStream = new ObjectOutputStream(byteOut);
        ) {
            outputStream.writeObject(src);
            try (ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
                 ObjectInputStream inputStream = new ObjectInputStream(byteIn);
            ) {
                return (List<T>) inputStream.readObject();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

    /**
     * 对对象进行深拷贝
     * 注意需要岁泛型类进行序列化(实现serializable)
     *
     * @param src
     * @param <T>
     * @return
     */
    public static <T> T deepCopy(T src) {
        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
             ObjectOutputStream outputStream = new ObjectOutputStream(byteOut);
        ) {
            outputStream.writeObject(src);
            try (ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
                 ObjectInputStream inputStream = new ObjectInputStream(byteIn);
            ) {
                return (T) inputStream.readObject();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

实体类

import java.io.Serializable;

/**
 * @Description
 * @Author saq
 * @Date 2023/2/20 10:36
 */
public class UserInfo implements Serializable {
    private Long id;private String name;
    private String hobby;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }public String getName() {
        return name;
    }

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

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}

 

posted @ 2023-02-21 11:10  蛋挞小子  阅读(310)  评论(0编辑  收藏  举报