JAVA实现深拷贝的几种方式代码
作者:Archie_java
准备
定义两个类用于测试拷贝,类内容如下,目的是深拷贝一个User类的对象:
@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,另外比照方法四同类的类库也能实现
到此这篇关于JAVA实现深拷贝的几种方式的文章就介绍到这了,更多相关JAVA实现深拷贝内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!