深拷贝、浅拷贝的写法_深拷贝和浅拷贝的区别及实现方式

deer332025-10-19技术文章37

一、概念

1.浅拷贝:将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用。

2.深拷贝:创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”。

简单一句话:浅拷贝只复制对象引用,深拷贝全部

二、4种深拷贝方式

了解一下就行了,到时候想用的时候知道有这个方式即可。

1、传统new(推荐)

Student student = new Student();
student.setStuId(1234);
student.setStuName("xyyyyy");
Student studentCopy = new Student();
studentCopy.setStuId(student.getStuId());
studentCopy.setStuName(student.getStuName());

笨方法,字段少的,还是可以用的。

2、实现cloneable(推荐)

不推荐的原因是,要每个对象都实现cloneable,比较麻烦。

public class A implements Cloneable {   
    public String name[];   
    public A(){   
        name=new String[2];   
    }   
    public Object clone() {   
        A o = null;   
        try {   
            o = (A) super.clone();   
        } catch (CloneNotSupportedException e) {   
            e.printStackTrace();   
        }   
        return o;   
    }   
}  
A copy = new A();
copy.clone());

3、序列化方式(推荐

public static Object deepCopy(Object object)  {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = null;
Object dest = null;
try {
    out = new ObjectOutputStream(byteOut);
    out.writeObject(object);
    ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
    ObjectInputStream in = new ObjectInputStream(byteIn);
    dest =  in.readObject();
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}
return dest;
}

注意:要拷贝的对象必须实现序列化。

4、JSON转化(推荐 )

原理:可以先将对象转化为JSON,再序列化为对象

Map mapCopy = JSONObject.parseObject(JSON.toJSONString(map), Map.class);

三、4种浅拷贝

1、spring的BeanUtils(推荐)

BeanUtils.copyProperties(sourceBean,TargetBean);

有spring环境就可以用

2、apache的BeanUtils(推荐)

性能不行不推荐

3、MapStruct(推荐)

MapStruct是用于生成类型安全的bean映射类的Java注解处理器。

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.3.1.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.3.1.Final</version>
</dependency>

静态方法调用

@Mapper
public interface ConvertMapper {
    ConvertMapper INSTANCE = Mappers.getMapper(ConvertMapper.class);
 // 通过在Mappings注解里配置多个mapping,实现字段不一致的情况的映射
 @Mappings(
    @Mapping(target = "",source = "")
    )
    MappingTaskCacheDto mapToTaskDto(MappingTaskCacheDto mappingTaskCacheDto);
}
调用:
MappingTaskCacheDto mappingTaskCacheDto = BeanFactory.createMappingTaskCacheDto();
MappingTaskCacheDto mappingTaskCacheResult = ConvertMapper.INSTANCE.mapToTaskDto(mappingTaskCacheDto);

4、BeanCopier(推荐)

spring自带依赖,略麻烦,不推荐。

BeanCopier beanCopier = BeanCopier.create(MappingTaskCacheDto.class, MappingTaskCacheDto.class, false);
//创建源对象并赋值数据
MappingTaskCacheDto mappingTaskCacheDto = createMappingTaskCacheDto();
//创建目标对象
MappingTaskCacheDto mappingTaskCacheResult = new MappingTaskCacheDto();
beanCopier.copy(mappingTaskCacheDto,mappingTaskCacheResult,null);

三、list浅拷贝

上面的浅拷贝,在list中也能用,但是list有更方便的写法。

1、构造(推荐)

List<User> destList=new ArrayList<>(srcList);

2、addAll(推荐)

addAll也能达到复制的效果。

List<User> destList=new ArrayList<>(); 
destList.addAll(srcList);

3、arrayCopy(推荐)

比较麻烦,不是很推荐。

Student[] srcPersons=list.toArray(new Student[0]);
Student[] studentArr=new Student[srcPersons.length];
System.arraycopy(srcPersons, 0, studentArr, 0, srcPersons.length);
List<Student> listCoppys = Arrays.asList(studentArr);

4、传统复制(推荐)

List<User> destList=new ArrayList<>(srcList.size());  
for(User p : srcList){  
    destList.add(p);  
}

5、Collections.copy()

Collections.copy(list2, list1);

三、map浅拷贝

1、构造(推荐)

Map<String, Student> mapCopy = new HashMap<>(map);

2、putAll()

这个方法作为拷贝也是可以的。

Map<String, Student> map = new HashMap<>();
Map<String, Student> mapCopy = new HashMap<>();
mapCopy.puAll(map);

总结

深拷贝就是拷贝后相当于两个不相干的对象;

浅拷贝,如果有包含子对象,就会互相影响。如果是基础类型,就放心用浅拷贝了,怎么都不会互相影响。比如

List<String>
Map<String,String>

还有类里的基础类型

public class Student{
	private String stuName;
}