一、浅复制和深复制概念

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

深复制(深克隆): 被复制对象的所有变量都含有与原来对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象, 而不再试原有的那些被引用的对象。换言之,深复制把复制的对象所应用的对象都复制了一遍。

二、Java的Clone()方法 【定义在Object类中】

clone方法将对象复制一份并返回给调用者。

一般而言,clone()  方法满足:

1、对任何对象x,都有x.clone() != x

克隆对象与原对象不是一个对象

2、对任何的对象x,都有

x.clone().getClass() == x.getClass()

克隆对象与原对象的类型一样

3、如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立

二、浅复制Demo

public class CloneTest1 {

    public static void main(String[] args) throws CloneNotSupportedException {
Student student = new Student();
student.setAge(20);
student.setName("Larry"); Student student2 = (Student)student.clone();
System.out.println(student2.getAge());
System.out.println(student2.getName()); System.out.println("-----------------------"); student2.setName("Nick");
System.out.println(student.getName());
System.out.println(student2.getName()); }
} class Student implements Cloneable{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} @Override
public Object clone() throws CloneNotSupportedException {
Object object = super.clone();
return object;
}
}

打印结果

20
zhangsan
-----------------------
zhangsan
Lisi

 student2.setName("Nick"); 执行后,student2的name赋予新的值,指向新的空间。如下图

三、深复制
以下代码还是浅复制
public class CloneTest2 {

    public static void main(String[] args) throws CloneNotSupportedException {

        Teacher teacher = new Teacher();
teacher.setAge(40);
teacher.setName("Teacher zhang"); Student2 s1 = new Student2();
s1.setAge(20);
s1.setName("zhangsan");
s1.setTeacher(teacher); Student2 s2 = (Student2)s1.clone();
System.out.println(s2.getAge());
System.out.println(s2.getName()); teacher.setName("Teacher Li"); System.out.println(s2.getTeacher().getAge());
System.out.println(s2.getTeacher().getName()); }
} class Teacher {
private int age;
private String name; public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} } class Student2 implements Cloneable{
private int age;
private String name; private Teacher teacher; public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public Object clone() throws CloneNotSupportedException {
Object object = super.clone();
return object;
}
}

修改成深复制

Teacher也实现Clone方法

然后改写Student的Clone方法

clone Student的时候,修改Teacher。

修改后的完整代码:

public class CloneTest2 {

	public static void main(String[] args) throws CloneNotSupportedException {

		Teacher teacher = new Teacher();
teacher.setAge(40);
teacher.setName("Teacher zhang"); Student2 s1 = new Student2();
s1.setAge(20);
s1.setName("zhangsan");
s1.setTeacher(teacher); Student2 s2 = (Student2)s1.clone();
System.out.println(s2.getAge());
System.out.println(s2.getName()); teacher.setName("Teacher Li"); System.out.println(s2.getTeacher().getAge());
System.out.println(s2.getTeacher().getName()); }
} class Teacher implements Cloneable{
private int age;
private String name; public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} @Override
public Object clone() throws CloneNotSupportedException { return super.clone();
} } class Student2 implements Cloneable{
private int age;
private String name; private Teacher teacher; public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public Object clone() throws CloneNotSupportedException {
Student2 student2 = (Student2)super.clone();
student2.setTeacher((Teacher)student2.getTeacher().clone());
return student2;
}
}

  

五、利用序列化来做深复制(最简单也是最多的一种方式)

1、使用Clone方法实现深复制存在的缺点: 存在多个引用的成员变量,将做多次处理。

如上图做了一次处理,如果有多个应用,将做多次处理。

2、序列化/反序列化

把对象写到流里的过程是序列化(Serilization)过程,而把对象从流中读取出来的过程则叫饭序列化(Deserialization)过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面

1)在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来,便可以重建对象。

2)这样做的前提示对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象是否设成transient,从而将之排除在复制过程之外。

3)Code

public class CloneTest3 {

	public static void main(String[] args) throws Exception {

		Teacher3 teacher = new Teacher3();
teacher.setAge(40);
teacher.setName("Teacher zhang"); Student3 s1 = new Student3();
s1.setAge(20);
s1.setName("zhangsan");
s1.setTeacher(teacher); Student3 s2 = (Student3)s1.deepCopy();
System.out.println(s2.getAge());
System.out.println(s2.getName());
System.out.println("-------------"); System.out.println(s2.getTeacher().getAge());
System.out.println(s2.getTeacher().getName()); s2.getTeacher().setAge(50);
s2.getTeacher().setName("Teacher Li"); System.out.println(s1.getTeacher().getAge());
System.out.println(s1.getTeacher().getName()); }
} class Teacher3 implements Serializable{ //private static final long serialVersionUID = 675697793444541314L;
private int age;
private String name; public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} } class Student3 implements Serializable{ //private static final long serialVersionUID = -7008294898863009451L;
private int age;
private String name; private Teacher3 teacher; public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} public Teacher3 getTeacher() {
return teacher;
}
public void setTeacher(Teacher3 teacher) {
this.teacher = teacher;
} public Object deepCopy() throws Exception {
//将对象写入流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//从流中读取对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
} }

  打印结果:

20
zhangsan
-------------
40
Teacher zhang
40
Teacher zhang

  

六、关于实现Seriallizable接口的类中的serialVersionUID问题

如果你的对象序列化后存在硬盘上面后,可是后来你更改了类的field(增加或减少或改名),当你反序列化时,就会出现Execption的,这样就会造成不兼容性的问题。

但当serialVersionUID相同时,它就会将不一样的field以type的缺省值Deserialize,这样可以避开不兼容的问题。

深拷贝(deep clone)与浅拷贝(shallow clone)的更多相关文章

  1. 深拷贝(deep clone)与浅拷贝(shallow clone)

    深拷贝(deep clone)与浅拷贝(shallow clone) 浅复制(浅克隆):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复 ...

  2. java的clone()、浅拷贝与深拷贝

    clone()方法是Object的native方法.protected native Object clone() throws CloneNotSupportedException;  声明为pro ...

  3. Java:浅克隆(shallow clone)与深克隆(deep clone)

    Summary 浅克隆与深克隆对于JavaSE来说,是个难度系数比较低的概念,但不应该轻视它. 假设一个场景:对于某个list,代码里并没有任何对其的直接操作,但里面的元素的属性却被改变了,这可能就涉 ...

  4. 由Python的浅拷贝(shallow copy)和深拷贝(deep copy)引发的思考

    首先查看拷贝模块(copy)发现: >>> help(copy)Help on module copy:NAME    copy - Generic (shallow and dee ...

  5. copy&mutableCopy 浅拷贝(shallow copy)深拷贝 (deep copy)

    写在前面 其实看了这么多,总结一个结论: 拷贝的初衷的目的就是为了:修改原来的对象不能影响到拷贝出来得对象 && 修改拷贝出来的对象也不能影响到原来的对象 所以,如果原来对象就是imm ...

  6. shallow clone

    shallow clone 浅克隆经常在一些大型仓库中很有用——不用花费大量时间去clone一个完整的仓库,仅仅checkout出来某个分支(如master)的最新N次递交: git clone -- ...

  7. Java中的深拷贝(深复制)和浅拷贝(浅复制)

    深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在C++语言中,若不弄懂,则会在delete的时候出问题,但是我们在这幸好用的是Java.虽然java自动管理对象的回收,但对于深拷贝(深复 ...

  8. git clone 和 download 不一样,能用git clone 就用git clone,download的代码,经常出现安装bug

    git clone 和 download 不一样,能用git clone 就用git clone,download的代码,经常出现安装bug

  9. 浅谈浅克隆(shallow clone)和 深克隆(deep clone)

    区别就在于是否对对象中的引用变量所指向的对象进行拷贝. 1.浅克隆/浅复制/浅拷贝 浅拷贝是指在拷贝对象时,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用进行拷贝,没有对引用指向 ...

随机推荐

  1. Centos7安装Openresty和orange

    1.说明 以下全部操作均已root用户执行 2.安装 2.1 安装依赖 yum install readline-devel pcre-devel openssl-devel gcc 2.2 下载op ...

  2. c# BufferedStream 类

  3. python 执行系统命令模块比较

    python 执行系统命令模块比较 1.os.system模块 仅仅在子终端运行命令,返回状态码,0为成功,其他为失败,但是不返回执行结果 如果再命令行下执行,结果直接打印出来 >>> ...

  4. Proxmox 命令使用方法

    proxmox 虚拟机使用命令介绍 qm <command> <vmid> [OPTIONS]                                          ...

  5. HDU-4190-Number Sequence-容斥原理+多重集和的r组合

    HDU-4190-Number Sequence-容斥原理+多重集和的r组合 [Problem Description] 给你\(n\)个数\(b_i\),问有多少个长度为\(n\)序列\(a_i\) ...

  6. java在win系统下的环境的搭建

    学习Java第一步是配置本地开发环境,学习最基本的桌面开发,下面以win7为例配置Java开发环境,安装JDK的时候会默认安装JRE,根据提示安装就可以了. 首先去官网下载适合系统版本的JDK,下载地 ...

  7. jemeter 查看结果树 分析

    查看结果树,可以看到测试通过,通过 的测试通常为绿色.红色则代表失败了.可以查看到取样器结果,请求,响应数据 取样器结果中可以查看到响应头,响应数据大小,响应时间等信息. Thread Name: 线 ...

  8. Spring源码窥探之:@Value

    1. 首先定义实体 /** * @author 70KG * @Title: Apple * @Description: 苹果实体 * @date 2018/10/22下午9:26 * @From w ...

  9. 4、MapReduce思想、运行机制

    MapReduce 离线计算框架 分而治之 input > map > shuffle > reduce > output 分布式并行的计算框架 将计算过程分为两个阶段,Map ...

  10. 使用bufio包和函数式变成实现类似python生成器效果

    package main import ( "bufio" "fmt" "io" "strings" ) type in ...