JAVA几种方式实现深拷贝
准备
定义两个类用于测试拷贝,类内容如下,目的是深拷贝一个User类的对象:文章来源:https://www.toymoban.com/news/detail-704431.html
@Data
@Accessors(chain = true)
public class User {
private Integer id;
private Integer age;
private String name;
private Car car;
private String category;
}
@Data
@Accessors(chain = true)
public class Car {
private Integer id;
private String color;
private String name;
}
实现
package com.demo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.*;
@Data
@Accessors(chain = true)
public class User implements Cloneable, Serializable {
private Integer id;
private Integer age;
private String name;
private Car car;
private String category;
@Override
public User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
/**
* 方法一:最原始的实现方式,通过构造方法手创建
* 优点:
* 1.实现简单直观
* 2.不需要依赖额外的接口和第三方包
* 缺点:
* 1.成员变量发生变动需要修改方法,不满足开闭原则;
* 2.不具有可复用性;
*/
public User copyUser1() {
User copyUser = new User()
.setId(this.getId())
.setName(this.getName())
.setAge(this.getAge())
.setCategory(this.getCategory());
if (this.getCar() != null) {
copyUser.setCar(new Car().setId(this.getCar().getId())
.setColor(this.getCar().getColor())
.setName(this.getCar().getName()));
}
return copyUser;
}
/**
* 方法二:使用Object的clone方法实现
* 优点:
* 1.较方式1实现更简单,不需要关注copy细节;
* 2.不需要依赖第三方包;
* 3.不修改引用类型成员变量不需要修改代码
* 缺点:
* 1.需要实现Cloneable,重写父类clone方法,不满足里式替换;
* 2.且引用类型成员变量发生变动需要修改方法,不满足开闭原则;
* 3.不具有可复用性;
*/
public User copyUser2() throws CloneNotSupportedException {
User cloneUser = this.clone();
if(this.getCar() != null) {
cloneUser.setCar(this.getCar().clone());
}
return cloneUser;
}
/**
* 方法三:使用Java自带的流方式实现
* 优点:
* 1.不破坏类的封装,无需了解被copy对象的内部
* 2.不需要依赖第三方包
* 3.代码可复用
* 缺点:
* 1.需要实现Serializable接口,会有额外的开销
*/
public User copyUser3() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (User) ois.readObject();
}
/**
* 方法四:使用第三方包Jackson实现
* 优点:
* 1.不破坏类的封装,无需了解被copy对象的内部
* 2.不需要实现接口
* 3.代码可复用
* 缺点:
* 1.需要依赖第三方包
* 2.内部实现复杂
*/
public User copyUser4() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(objectMapper.writeValueAsString(this),User.class);
}
}
验证
package com.demo;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) throws IOException, CloneNotSupportedException, ClassNotFoundException {
User user = new User().setAge(10).setName("李四").setId(3).setCategory("工人");
user.setCar(new Car().setName("保时捷").setId(999).setColor("黑色"));
User copyUser1 = user.copyUser1();
System.out.println("copyUser1:" + copyUser1);
System.out.println("copyUser1与user对象是否是同一个:" + (System.identityHashCode(user) == System.identityHashCode(copyUser1)));
System.out.println("copyUser1中的car与user中的car是否是同一个:"+(System.identityHashCode(user.getCar()) == System.identityHashCode(copyUser1.getCar())));
System.out.println("====================");
User copyUser2 = user.copyUser2();
System.out.println("copyUser2:" + copyUser2);
System.out.println("copyUser2与user对象是否是同一个:" + (System.identityHashCode(user) == System.identityHashCode(copyUser2)));
System.out.println("copyUser2中的car与user中的car是否是同一个:"+(System.identityHashCode(user.getCar()) == System.identityHashCode(copyUser2.getCar())));
System.out.println("====================");
User copyUser3 = user.copyUser3();
System.out.println("copyUser3:" + copyUser3);
System.out.println("copyUser3与user对象是否是同一个:" + (System.identityHashCode(user) == System.identityHashCode(copyUser3)));
System.out.println("copyUser3中的car与user中的car是否是同一个:"+(System.identityHashCode(user.getCar()) == System.identityHashCode(copyUser3.getCar())));
System.out.println("====================");
User copyUser4 = user.copyUser4();
System.out.println("copyUser4:" + copyUser4);
System.out.println("copyUser4与user对象是否是同一个:" + (System.identityHashCode(user) == System.identityHashCode(copyUser4)));
System.out.println("copyUser4中的car与user中的car是否是同一个:"+(System.identityHashCode(user.getCar()) == System.identityHashCode(copyUser4.getCar())));
}
}
验证结果
copyUser1:User(id=3, age=10, name=李四, car=Car(id=999, color=黑色, name=保时捷), category=工人)
copyUser1与user对象是否是同一个:false
copyUser1中的car与user中的car是否是同一个:false
====================
copyUser2:User(id=3, age=10, name=李四, car=Car(id=999, color=黑色, name=保时捷), category=工人)
copyUser2与user对象是否是同一个:false
copyUser2中的car与user中的car是否是同一个:false
====================
copyUser3:User(id=3, age=10, name=李四, car=Car(id=999, color=黑色, name=保时捷), category=工人)
copyUser3与user对象是否是同一个:false
copyUser3中的car与user中的car是否是同一个:false
====================
copyUser4:User(id=3, age=10, name=李四, car=Car(id=999, color=黑色, name=保时捷), category=工人)
copyUser4与user对象是否是同一个:false
copyUser4中的car与user中的car是否是同一个:false
结论
使用java原生推荐方法三,方法一、方法二缺点过于明显,第三方库的方式可以用方法四,spring boot默认的序列化反序列化就是Jackson,另外比照方法四同类的类库也能实现文章来源地址https://www.toymoban.com/news/detail-704431.html
到了这里,关于JAVA几种方式实现深拷贝的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!