浅谈java浅拷贝和深拷贝
前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。深拷贝:被复制对象的所有变量都含有与原来对象相同的值,而那些引用对象的变量将指向被复制过的新对象,而不再是原有 的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。
浅拷贝
无论是浅拷贝还是深拷贝都要用到clone()方法,所有类都继承于Object,clone方法定义于Object类中但没有实现,
而如果要使用clone方法,根据源码则必须实现Cloneable接口,java.lang.Cloneable是一个标志性接口不包含任何方法,根据注释clone方法是由C或C++其他本地语言实现的。
* @return a clone of this instance.
* @throws CloneNotSupportedException if the object's class does not
* support the {@code Cloneable} interface. Subclasses
* that override the {@code clone} method can also
* throw this exception to indicate that an instance cannot
* be cloned.
* @see java.lang.Cloneable
*/
protected native Object clone() throws CloneNotSupportedException;
实现浅拷贝:
package yunche.test.copy; /**
* @ClassName: Dog
* @Description:
* @author: yunche
* @date: 2018/08/25
*/
public class Dog implements Cloneable
{
public String color;
public int age; /**
* 引用变量
*/
public Erha erha; public static void main(String[] args) throws CloneNotSupportedException
{
Dog d = new Dog();
d.color="yellow";
d.age=2;
d.erha = new Erha();
d.erha.name = "二哈"; //此时clone方法为浅拷贝
Dog copyDog = (Dog)d.clone();
System.out.println(copyDog.color);
System.out.println(copyDog.age);
System.out.println(copyDog.erha.name); //hashcode不同,创建了新对象
System.out.println(d==copyDog);
System.out.println(d.hashCode());
System.out.println(copyDog.hashCode()); //hashcode相同,没有创建新的erha对象,只是复制了引用
System.out.println(copyDog.erha==d.erha);
System.out.println(copyDog.erha.hashCode());
System.out.println(d.erha.hashCode()); } private static class Erha
{
String name;
}
}

深拷贝
深拷贝对于基本数据类型进行值传递,对引用数据类型,创建一个新的对象。并复制其内容。怎么实现深拷贝呢?通常的方案有两种:1.序列化这个对象,再反序列化回来,就可以得到这个新的对象,序列化的规则需要我们自己来写。2.重写clone方法,我们可以对其内部引用类型的变量,再进行一次clone()。
序列化方式
序列化需要实现Serializable接口。
package yunche.test.copy; import java.io.*; /**
* @ClassName: Dog
* @Description:
* @author: yunche
* @date: 2018/08/25
*/
public class Dog implements Cloneable, Serializable
{
public String color;
public int age; /**
* 引用变量
*/
public Erha erha; public static void main(String[] args) throws CloneNotSupportedException
{
Dog d = new Dog();
d.color="yellow";
d.age=2;
d.erha = new Erha();
d.erha.name = "二哈"; Dog copyDog = (Dog)d.deepClone();
System.out.println(copyDog.color);
System.out.println(copyDog.age);
System.out.println(copyDog.erha.name); //hashcode不同,创建了新对象
System.out.println(d==copyDog);
System.out.println(d.hashCode());
System.out.println(copyDog.hashCode()); //hashcode不同,创建新的erha对象,实现了深拷贝
System.out.println(copyDog.erha==d.erha);
System.out.println(copyDog.erha.hashCode());
System.out.println(d.erha.hashCode()); } public Object deepClone()
{
File f = new File("dog.obj");
Object obj =null;
try(FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis))
{
oos.writeObject(this);
obj = ois.readObject();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
return obj;
} private static class Erha implements Serializable
{
String name;
}
}

重写clone
package yunche.test.copy; import java.io.*; /**
* @ClassName: Dog
* @Description:
* @author: yunche
* @date: 2018/08/25
*/
public class Dog implements Cloneable
{
public String color;
public int age; /**
* 引用变量
*/
public Erha erha; public static void main(String[] args) throws CloneNotSupportedException
{
Dog d = new Dog();
d.color="yellow";
d.age=2;
d.erha = new Erha();
d.erha.name = "二哈"; //重新clone方法,实现深拷贝
Dog copyDog = (Dog)d.clone();
System.out.println(copyDog.color);
System.out.println(copyDog.age);
System.out.println(copyDog.erha.name); //hashcode不同,创建了新对象
System.out.println(d==copyDog);
System.out.println(d.hashCode());
System.out.println(copyDog.hashCode()); //hashcode不同,创建新的erha对象,实现了深拷贝
System.out.println(copyDog.erha==d.erha);
System.out.println(copyDog.erha.hashCode());
System.out.println(d.erha.hashCode()); } @Override
public Object clone()
{
try
{
Dog dog = (Dog)super.clone();
dog.erha = (Erha) this.erha.clone();
return dog; }
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
return null;
} public static class Erha implements Cloneable
{
String name; @Override
public Object clone()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
return null;
}
}
}

参考资料
https://segmentfault.com/a/1190000010648514
浅谈java浅拷贝和深拷贝的更多相关文章
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 浅谈C#浅拷贝和深拷贝
近来爱上一本书<编写高质量代码,改善C#程序的157个建议>,我想很多人都想编写高质量的代码,因为我们不仅仅是码农,更是一名程序员. 从今天开始,我将每天和大家分享这本书中的内容,并加上自 ...
- java基础(十七)----- 浅谈Java中的深拷贝和浅拷贝 —— 面试必问
假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...
- 浅谈Javascript 浅拷贝和深拷贝的理解
javascript中存储对象都是存地址的. 浅拷贝:浅拷贝是都指向同一块内存区块,浅拷贝共用同一内存地址,你改值我也变.如果拷贝的对象里面的值是一个对象或者数组,它就是浅拷贝,拷贝的知识引用地址. ...
- Java 浅拷贝、深拷贝,你知多少?
这是今天我们在技术群里面讨论的一个知识点,讨论的相当激烈,由于对这一块使用的比较少,所以对这一块多少有些盲区.这篇文章总结了所讨论的内容,希望这篇文章对你有所帮助. 在 Java 开发中,对象拷贝或者 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
随机推荐
- SpringMVC之请求参数的获取方式
转载出处:https://www.toutiao.com/i6510822190219264516/ SpringMVC之请求参数的获取方式 常见的一个web服务,如何获取请求参数? 一般最常见的请求 ...
- 蓝桥 ADV-233 算法提高 队列操作 【STL】
算法提高 队列操作 时间限制:1.0s 内存限制:256.0MB 问题描述 队列操作题.根据输入的操作命令,操作队列(1)入队.(2)出队并输出.(3)计算队中元素个数并输出. ...
- sql%found sql%notfound sql%rowcount sql%isopen
原文引入:http://blog.csdn.net/mh942408056/article/details/6949325 sql%found sql%notfound sql%rowcount sq ...
- 【bug】【userAgent】极速模式与非极速模式存在差异
UC浏览器 Android 极速模式 UC浏览器 Android 非极速模式
- 2010–2011, NEERC, Northern Subregional C.Commuting Functions
C.Commuting Functions 由于要求答案字典序最小,我们肯定希望从g(1)开始对函数g进行赋值,于是又公式f(g(x))=g(f(x)) 设f(x)=i 我们推导出 由于f是双射,当i ...
- 洛谷 P3960 [ NOIP 2017 ] 列队 —— 线段树
题目:https://www.luogu.org/problemnew/show/P3960 NOIP 题,不用很复杂的数据结构...但又参考了许多: 要求支持维护删除第 k 个和在末尾插入的数据结构 ...
- 杂项-Java:MyBatis
ylbtech-杂项-Java:MyBatis 1.返回顶部 1. MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundatio ...
- Java中的经典算法之冒泡排序
原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将 ...
- mysql之distinct
记录一下这几天看mysql必知必会的小知识点: 关于mysql查询不同的行 比如记录表中 查询有多少个城市 可能查出很多城市 可以用distinct 来解决这个问题 SELECT DISTINCT c ...
- 全面学习ORACLE Scheduler特性(4)创建和管理Schedule
三.使用Schedules 10g 中新推出的SCHEDULER可能确实会让很多初接触的朋友感觉晕头晕脑,相比之前的jobs,SCHEDULER中新增的概念太多.比如说jobs,仍然可以理解成之前版本 ...