java对象拷贝
1、介绍
Java编写代码中,对象的拷贝是一个常见的操作。根据拷贝的层次和方式不同,可以分为深拷贝、浅拷贝和零拷贝
2、深拷贝
深拷贝是一种创建对象副本的方法,其中新对象与原始对象完全独立。这就意味着新对象的所有字段都被复制,并且如果字段是引用类型,那么递归地执行深拷贝,以确保新对象和原始对象不共享任何内部对象。
1、手动new实现:
通过创建一个新的对象,并逐个复制字段的值。如果字段是引用类型,需要递归地创建该字段的新实例,只不过这个过程比较繁琐。
2、使用序列化的方式
将对象序列化为字节流,然后再反序列化回一个新对象。这种方法要求对象及其所有组成部分都是可序列化的。
1、Apache Commons Lang序列化
可用性强,新增成员变量不需要修改拷贝方法
底层实现较复杂
需要引入Apache Commons Lang第三方JAR包
拷贝类(包括其成员变量)需要实现Serializable接口
序列化与反序列化存在一定的系统开销,Java 序列化: 是 Java 提供的一种内建机制,使用对象的序列化和反序列化机制来创建对象的深拷贝。这种方法依赖于 Java 的 ObjectOutputStream
和 ObjectInputStream
,并通过二进制数据进行存储。
- 序列化:
SerializationUtils.clone()
首先将对象序列化到一个ByteArrayOutputStream
中。这个过程将对象的状态转换为字节流。 - 反序列化: 然后,它从
ByteArrayInputStream
中读取字节流,并通过反序列化过程将其转换回对象。这些字节流中的数据完全描述了对象的状态,包括它所引用的所有对象。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3:3.5</version>
</dependency>
@Data
public class User implements Serializable {
private String name;
private Integer age;
}
调用SerializationUtils工具类,实现深拷贝(注意:SerializationUtils不能直接拷贝List类型)
user1的改变不会导致user2的改变,从而实现深拷贝
package com.shuizhu.study2;
import org.apache.commons.lang3.SerializationUtils;
//Apache Commons Lang序列化实现对象的深拷贝
public class Study01 {
public static void main(String[] args) {
User user1 = new User();
user1.setName("张三");
user1.setAge(18);
User user2 = SerializationUtils.clone(user1);
System.out.println("user1未改变前,user2的名字为:" + user2.getName());
user1.setName("李四");
System.out.println("user1改变后,user2的名字为:" + user2.getName());
}
}
List类型深拷贝
package com.shuizhu.study2;
import java.io.Serializable;
import java.util.List;
/**
* 用于深拷贝时,不需要去遍历List<User>集合,只需要拷贝UserCopyDTO 对象就可以
* 获取到新的List<User>集合
*/
@Data
public class UserCopyDTO implements Serializable {
//必须实现Serializable接口
private List<User> users;
}
结果:list1改变后拷贝的list2不会随之改变
import org.apache.commons.lang3.SerializationUtils;
import java.util.ArrayList;
import java.util.List;
//Apache Commons Lang序列化实现List的深拷贝
public class Study02 {
public static void main(String[] args) {
List<