前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。深拷贝:被复制对象的所有变量都含有与原来对象相同的值,而那些引用对象的变量将指向被复制过的新对象,而不再是原有 的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

浅拷贝

  无论是浅拷贝还是深拷贝都要用到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浅拷贝和深拷贝的更多相关文章

  1. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  2. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  3. 浅谈C#浅拷贝和深拷贝

    近来爱上一本书<编写高质量代码,改善C#程序的157个建议>,我想很多人都想编写高质量的代码,因为我们不仅仅是码农,更是一名程序员. 从今天开始,我将每天和大家分享这本书中的内容,并加上自 ...

  4. java基础(十七)----- 浅谈Java中的深拷贝和浅拷贝 —— 面试必问

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  5. 浅谈Javascript 浅拷贝和深拷贝的理解

    javascript中存储对象都是存地址的. 浅拷贝:浅拷贝是都指向同一块内存区块,浅拷贝共用同一内存地址,你改值我也变.如果拷贝的对象里面的值是一个对象或者数组,它就是浅拷贝,拷贝的知识引用地址.  ...

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

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

  7. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  8. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  9. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

随机推荐

  1. Android Studio:Gradle project refresh failed. 解决方法

    事件 换了个电脑,Android Studio拷过来,重新配置后,打开已有的项目,报错: Gradle project refresh failed. Connection timed out: co ...

  2. js验证手机号,身份证,车牌号验证

    js验证手机号  <input type="text" class="identificationno"> // 身份证号码为15位或者18位,15 ...

  3. bzoj1531

    背包+倍增 直接背包跑不过去,那么我们把容量分成二进制,然后原来需要枚举c次就只用枚举log(c)次了,这样还是能组合出任意小于等于c的组合方案 #include<bits/stdc++.h&g ...

  4. 如何在BCGControlBar工程的工具栏里面新增下拉列表控件

    通常情况下,工具栏里面都是一些按钮和图片,很少可以看到下拉列表控件,但是在某些应用场合,也需要用到下拉列表控件.今天在这里就简单讲解下如何在工具栏里添加下拉列表控件.   添加的过程也比较简单,在CM ...

  5. js的多种数值分类相加,数据先后没有顺序,不确定同类数据多少

    下面是js源码片段.看的是思想. <script type="text/javascript"> deg_countMyChart = function(deptcod ...

  6. P4097 [HEOI2013]Segment

    传送门 简单来说就是对于每条线段,先把它拆成\(O(logn)\)条,然后对于每一条再\(O(logn)\)判断在所有子区间的优劣程度 //minamoto #include<bits/stdc ...

  7. BEM --Yandex的CSS 命名方法论

    人们问我最多的问题之一是在CSS类名中--和__是什么意思?它们的出现是源于BEM和Nicolas Gallagher... BEM的意思就是块(block).元素(element).修饰符(modi ...

  8. Mybatis Generator插件升级版

    一.目的: 1. *mapper.java 文件名称 改为*DAO.java2. mapper以及mapper.xml 重复执行,只会覆盖原模板方法,不会覆盖自定义方法3. 实体类添加中文注释 二.步 ...

  9. STL之set和multiset

    set是与集合相关的容器,STL为我们提供了set的实现,在编程题中遇见集合问题直接调用是十分方便 SET set模版类的定义在头文件<set>中. 定义set对象的示例代码如下: set ...

  10. Android 性能优化(20)多核cpu入门:SMP Primer for Android

    SMP Primer for Android 1.In this document Theory Memory consistency models Processor consistency CPU ...