JAVA几种方式实现深拷贝
2021/7/15 1:04:50
本文主要是介绍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几种方式实现深拷贝的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
- 2024-11-24细说敏捷:敏捷四会之每日站会
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解