在java开发中,有时我们需要复制对象,并且确保修改复制得到的对象不会影响原来的对象。

于是,有些人可能会写出类似以下的代码:

public class CloneTest {
public static void main(String[] args) {
JSONObject paramJson= new JSONObject();
paramJson.put("age",26);
paramJson.put("name","lin");
JSONObject cloneJson= paramJson;
cloneJson.put("test",27);
System.out.println("paramJson:"+paramJson.toString());
System.out.println("cloneJson:"+cloneJson.toString());
}
}

运行结果为:

paramJson:{"age":27,"name":"lin"}
cloneJson:{"age":27,"name":"lin"}

发现赋值得到的对象改变时,原来的对象也随之改变。

值传递与引用传递中已经讲到,

引用类型传参或赋值,新的对象改变时,原来的对象也会改变。

那么,如何确保修改复制得到的新对象不会影响原来的对象呢?

深拷背和浅拷背

复制对象,修改新对象不会影响原来的对象。这其实就是深拷背。

而修改复制得到的新对象会影响原来的对象,则是浅拷背。


从值和引用的角度理解,概念如下:

1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用

2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”

在java的超类Object中,有一个clone()方法,默认的是浅拷背。

protected Object clone()
throws CloneNotSupportedException

那么,如何实现深拷背呢?

深拷背的实现

有几个工具类可以使用深拷背。

1.BeanUtils。

注意,最好使用Spring的BeanUtils,不要用Apache-Commons的BeanUtils。

阿里巴巴java规范手册中提到,Apache BeanUtils性能较差,可以使用 Spring BeanUtils 或者 Cglib BeanCopier 来代替。

public class DeepCloneTest {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
JSONObject paramJson= new JSONObject();
paramJson.put("age",26);
paramJson.put("name","lin");
JSONObject cloneJson= new JSONObject();
BeanUtils.copyProperties(cloneJson,paramJson);
cloneJson.put("test",27);
System.out.println("paramJson:"+paramJson.toString());
System.out.println("cloneJson:"+cloneJson.toString());
}
}

运行结果:

paramJson:{"name":"lin","age":26}
cloneJson:{"test":27}

2.apache-commons包的SerializationUtils。**SerializationUtils要求对象必须实现序列化接口 **

public class DeepCloneTest {
public static void main(String[] args) {
JSONObject paramJson= new JSONObject();
paramJson.put("age",26);
paramJson.put("name","lin");
JSONObject cloneJson=SerializationUtils.clone(paramJson);
cloneJson.put("age",27);
System.out.println("paramJson:"+paramJson.toString());
System.out.println("cloneJson:"+cloneJson.toString());
}
}

运行结果:

paramJson:{"name":"long","age":26}
cloneJson:{"name":"long","age":27}

java复制对象之深拷背的更多相关文章

  1. Java中对象的深复制和浅复制详解

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...

  2. c# 对象的深拷备

    C# 引用类型对象在拷备时,一般有浅拷备与深拷备,浅拷备指向的是同一对象的引用地址,一个对象的修改必然会影响另一个对象,而深拷备是直接拷备对象的内容,而不是引用,拷备后的对象拥有新的引用,这里主要介绍 ...

  3. java 复制对象 (克隆接口 与 序列化)

    关于java对象复制我们在编码过程经常会碰到将一个对象传递给另一个对象,java中对于基本型变量采用的是值传递,而对于对象比如bean传递时采用的是应用传递也就是地址传递,而很多时候对于对象传递我们也 ...

  4. java复制对象,复制对象属性,只可复制两个对象想同的属性名。也可自定义只复制需要的属性。

    注意:使用时copy()方法只会复制相同的属性.常用的copy()方法.以下为封装的工具和使用方式. 1.封装类 import java.util.Map; import java.util.Weak ...

  5. java hasmap对象的深复制实现:字节码复制和对象序列化成字符串复制比较。

    /** * Created by Administrator on 2016/11/23. */ public class test { public static void main(String[ ...

  6. js 复制对象的深复制与浅复制

    1.潜复制(修改新对象会改变原对象) var baz = {a:'hello', b: {c:'my', d:'friend'}} var foo = baz foo.a="better&q ...

  7. Java中的clone()----深复制,浅复制

    这篇文章主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他 ...

  8. OC基础16:复制对象

    "OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.浅复制即是指针赋值,复制对象的修改会影 ...

  9. java对象实现深复制的方法

    p2 = (Person)org.apache.commons.lang3.ObjectUtils.cloneBean(p); Person p2 = new Person(); p2 = (Pers ...

随机推荐

  1. android中app卡顿优化问题

     所谓app卡顿原因就是在运行时出现了丢帧,还可能是UI线程被阻塞.首先来一下丢帧现象,android每16ms会对界面进行一次渲染,如果app的绘制.计算等超过了16ms那么只能等下一个16ms才能 ...

  2. Cheat Engine 创建线程

    打开游戏 扫描出阳光地址 打开自动汇编 激活测试 每次激活,阳光都会自增

  3. 老大难的GC原理及调优,这下全说清楚了

    概述 本文介绍GC基础原理和理论,GC调优方法思路和方法,基于Hotspot jdk1.8,学习之后将了解如何对生产系统出现的GC问题进行排查解决 阅读时长约30分钟,内容主要如下: GC基础原理,涉 ...

  4. 购买了一台阿里云ECS后安装Java项目运行环境

    在docker等虚拟化技术大行其道的今天,我原本也想在我买的ECS服务器里全系使用docker技术,只可惜在我尝试后发现我的ECS配置不够高,整个服务器卡到爆炸,无奈只能使用最原始的方式. 我买的服务 ...

  5. 在线java堆栈分析工具

    1:工具地址  https://gceasy.io/ft-dashboard-web.jsp 2:在线分析结果       

  6. php命令模式(command pattern)

    ... <?php /* The command pattern decouples the object that executes certain operations from objec ...

  7. “IOS11不再信赖WOSIGN证书”公众号运营者如何应对

    ptd->_thandle = (uintptr_t)(-1); {{}/*** 传入需要的参数,设置给*/{}给Fragment添加newInstance方法,将需要的参数传入,设置到bund ...

  8. 玩转Spring--消失的事务@Transactional

    消失的事务 端午节前,组内在讨论一个问题: 一个没有加@Transactional注解的方法,去调用一个加了@Transactional的方法,会不会产生事务? 文字苍白,还是用代码说话. 先写一个@ ...

  9. LOJ6070 基因

    基因 给定一个长度为 \(n\) 的字符串 \(s\),有 \(q\) 组询问,每个询问给定 \(l,r\),询问 \(s[l..r]\) 中有多少本质不同的回文子串. 强制在线.\(n\leq 10 ...

  10. JQuery系列(5) - Deferred对象

    从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. 简单说,deferred对象就是jQuery的回调函数解决方案.在英语中,defer的意思是"延迟" ...