目录

  • 浅拷贝介绍
  • 深拷贝介绍
  • 拷贝的工具类推荐

浅拷贝介绍

拷贝出当前对象的一个副本,这个新对象和当前对象处于不同的堆内存中,两个对象的基本数据类型的值完全一样,但是引用数据类型还是指向同一个对象的。

深拷贝介绍

深拷贝拷贝出当前对象的一个副本,这个新对象和当前对象处于不同的堆内存中,两个对象的基本数据类型的值完全一样,引用数据类型指向的对象也拷贝出了一份一模一样的副本。

可以看到我们如果在拷贝对象时不清楚深拷贝和浅拷贝的话很容易出现一些未知的异常,接下来我们用代码来演示一下

public class User implements Cloneable {private String name;private Address address;public String getName() {return name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public void setName(String name) {this.name = name;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}
}
public class Address {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}
public class CopyDemo {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address();address.setAddress("杭州市");User user = new User();user.setName("jack");user.setAddress(address);User newUser = (User) user.clone();System.out.println("拷贝后对象的address:"+newUser.getAddress().getAddress());user.getAddress().setAddress("湖州市");System.out.println("修改了拷贝前对象的address后,拷贝后对象的address:"+newUser.getAddress().getAddress());}}

输出值:
拷贝后对象的address:杭州市
修改了拷贝前对象的address后,拷贝后对象的address:湖州市

可以看到这里我们修改了拷贝前对象的Address,但是拷贝后对象Address也被改变了,由此可得拷贝前和拷贝后的Address执行的是堆内存中的同一个地址
科普:这里浅拷贝使用的是Jdk提供的Cloneable,使用时需要拷贝的对象实现Cloneable接口并且重写Object的clone()方法,Cloneable没有任何定义,只是一种规范。

深拷贝最容易想到的是使用Serializable接口序列化

public class User implements Cloneable,Serializable{private String name;private Address address;public String getName() {return name;}public User deepCopy() throws IOException, ClassNotFoundException {// 写入字节流ByteArrayOutputStream out = new ByteArrayOutputStream();ObjectOutputStream obs = new ObjectOutputStream(out);obs.writeObject(this);obs.close();// 分配内存,写入原始对象,生成新对象ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());ObjectInputStream ois = new ObjectInputStream(ios);// 返回生成的新对象User newUser = (User) ois.readObject();ois.close();return newUser;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public void setName(String name) {this.name = name;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}
}
public class Address implements Serializable {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}
public class CopyDemo {public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {Address address = new Address();address.setAddress("杭州市");User user = new User();user.setName("jack");user.setAddress(address);// 浅拷贝User newUser = (User) user.clone();// 深拷贝User newUser2 = user.deepCopy();System.out.println("拷贝后对象的address:"+newUser.getAddress().getAddress());user.getAddress().setAddress("湖州市");System.out.println("修改了拷贝前对象的address后,拷贝后对象的address:"+newUser.getAddress().getAddress());System.out.println("修改了拷贝前对象的address后,深拷贝后对象的address:"+newUser2.getAddress().getAddress());}
}

输出:
拷贝后对象的address:杭州市
修改了拷贝前对象的address后,拷贝后对象的address:湖州市
修改了拷贝前对象的address后,深拷贝后对象的address:杭州市

使用序列化对象,然后在反序列化即可得到一个全新的对象,但是使用起来性能比较低,所以不推荐使用,作为了解即可。

拷贝的工具类推荐

1、commons-beanutils的介绍:commons-beanutils是Apache组织下的一个基础的开源库,其主要目的是利用反射机制对JavaBean的属性进行处理。

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {Address address = new Address();address.setAddress("杭州市");User user = new User();user.setName("jack");user.setAddress(address);User newUser = new User();// 把user对象内容拷贝到newUserBeanUtils.copyProperties(newUser,user);user.getAddress().setAddress("湖州市");System.out.println("修改了拷贝前对象的address后,拷贝后对象的address:"+newUser.getAddress().getAddress());}

输出:修改了拷贝前对象的address后,拷贝后对象的address:湖州市
可见BeanUtils.copyProperties是浅拷贝

2、Orika(极力推荐):Orika底层采用了javassist类库生成Bean映射的字节码,之后直接加载执行生成的字节码文件,因此在速度上比使用反射进行赋值会快很多,下面详细介绍Orika的使用方法

定义工具类:

public class OrikaMapperUtils {private static final MapperFacade mapperFacade;static {MapperFactory mapperFactory = new DefaultMapperFactory.Builder().useAutoMapping(true).mapNulls(true).build();mapperFacade = mapperFactory.getMapperFacade();}public static <S, D> void map(S from, D to) {mapperFacade.map(from, to);}public static <S, D> D map(S from, Class<D> clazz) {return mapperFacade.map(from, clazz);}public static MapperFacade getMapperFacade() {return mapperFacade;}public static <S, D> List<D> mapAsList(Iterable<S> source, Class<D> destinationClass) {return mapperFacade.mapAsList(source, destinationClass);}}
public class CopyUtilsDemo {public static void main(String[] args) {Address address = new Address();address.setAddress("杭州市");User user = new User();user.setName("jack");user.setAddress(address);List<User> users = new ArrayList<>();users.add(user);// 浅拷贝User newUser = new User();// 1、把user对象内容拷贝到newUserOrikaMapperUtils.map(user,newUser);// 2、把user对象内容拷贝到newUserUser newUser2 = OrikaMapperUtils.map(user,User.class);// 3、深拷贝集合List<User> users2 = OrikaMapperUtils.mapAsList(users,User.class);user.getAddress().setAddress("湖州市");System.out.println("newUser的address:"+newUser.getAddress().getAddress());System.out.println("newUser2的address:"+newUser.getAddress().getAddress());System.out.println("users2的address:"+users2.get(0).getAddress().getAddress());}
}

由上可见Orika包含了平时对拷贝的常用功能
1、对象到对象的的深拷贝
2、对象到Class类的深拷贝,即不同类型对象也可以拷贝
3、集合的深拷贝

java浅拷贝与深拷贝及拷贝工具推荐相关推荐

  1. java什么地方要用深拷贝,关于 Java 浅拷贝、深拷贝,你真的知道了吗?

    这是今天我们在技术群里面讨论的一个知识点,讨论的相当激烈,由于对这一块使用的比较少,所以对这一块多少有些盲区.这篇文章总结了所讨论的内容,希望这篇文章对你有所帮助. 在 Java 开发中,对象拷贝或者 ...

  2. Java 浅拷贝、深拷贝,你知多少?

    在 Java 开发中,对象拷贝或者说对象克隆是常有的事,对象克隆最终都离不开直接赋值.浅拷贝.深拷贝 这三种方式,其中直接赋值应该是我们最常用的一种方式吧,对于浅拷贝和深拷贝可能用的少,所以或多或少存 ...

  3. Java浅拷贝和深拷贝(一文足矣),及String类型的坑。

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/q258523454/article/d ...

  4. Java浅拷贝和深拷贝的方式

    文章目录 1. 前言 2. 概念介绍 2.1 拷贝 / 克隆的概念 2.2 为什么需要拷贝方法? 2.3 什么是浅拷贝?浅拷贝和深拷贝的区别是什么? 3. 深拷贝的实现方式 3.1 手动深拷贝 3.2 ...

  5. Java提高篇 —— Java浅拷贝和深拷贝

    一.前言 我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面比我们直接通过new生成对象来的快,特别是在大对象的生成上,使得性能 ...

  6. java 浅拷贝和深拷贝

    实现拷贝有几点: 1)实现Cloneable接口 2)重写Object类中的clone方法,并将可见性从protect改为public 3)克隆需要调用super.clone(),也就是Object的 ...

  7. java浅拷贝和深拷贝的区别_Java 浅拷贝与深拷贝的区别

    浅拷贝 什么是浅拷贝 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.即对象的浅拷贝会对"主"对象进行拷贝,但不会复制主对象里面的对象. ...

  8. Java 浅拷贝和深拷贝的理解和实现方式

    https://www.cnblogs.com/shakinghead/p/7651502.html https://blog.csdn.net/huwentao_totti/article/deta ...

  9. 深入浅出理解Java中数组的浅拷贝和深拷贝

    深入浅出带你理解Java中数组的浅拷贝和深拷贝 深浅拷贝的区别 深浅拷贝的区别 所谓浅拷贝,一般指的就是对象引用,例如 Teacher teacher = new Teacher(); teacher ...

  10. 谈一谈Java中的深拷贝和浅拷贝

    在 Java 开发中,对象拷贝或者说对象克隆是常有的事,对象克隆最终都离不开直接赋值.浅拷贝.深拷贝 这三种方式,其中直接赋值应该是我们最常用的一种方式吧,对于浅拷贝和深拷贝可能用的少,所以或多或少存 ...

最新文章

  1. Lua学习笔记(2)
  2. python用户界面导入图片_python学习笔记之11:图像用户界面
  3. 远程连接Ubuntu桌面配置
  4. 快速开发工作流_02_集成在线流程设计器
  5. redis 配置文件翻译
  6. red linux系统管理,Red hat Linux 系统管理篇 4
  7. cuda驱动版本显卡对应关系
  8. 图片一句话木马简单制作方法
  9. 织梦网站数据入库接口(实现图片本地化,自动图片打水印)【原创】
  10. Flutter性能优化—UI
  11. JS 实现驼峰式转下横线,下横线转驼峰式2
  12. 浏览器开机自启动及全屏配置
  13. Easypack之Alpine容器系列:Redmine
  14. eclipse解决js提示
  15. Hbase慢请求常规排查流程
  16. Spring之XML解析
  17. 四大查找ASL的总结
  18. HTML支持3,傲游浏览器3进一步完善HTML5特性支持
  19. 三星K9F1G08U0E(128MB,NAND FLASH) STM32平台驱动程序(模拟时序)
  20. JAVA毕业设计专家系统房产营销智能推荐系统计算机源码+lw文档+系统+调试部署+数据库

热门文章

  1. MySQL 实时同步 解决方案
  2. qnx 设备驱动开发_一种QNX系统的USB驱动加载方法与流程
  3. Android NDK开发1——开发流程+依赖外部so+生成自实现so+静态注册JNI+动态注册JNI
  4. Windows鼠标键盘(PS2)驱动框架
  5. html cm和px转换,px和cm换算长度单位 怎么把AI单位里的像素改成毫米?
  6. Java技术栈学习路线(不喜勿喷)
  7. oracle优化distinct,oracle 索引优化之distinct
  8. 【Push Kit】模拟服务端发送消息至客户端,测试消息发送功能(华为推送服务)
  9. 微信小程序倒计时功能
  10. Python快速入门教材推荐!