深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在C++语言中,若不弄懂,则会在delete的时候出问题,但是我们在这幸好用的是Java。虽然java自动管理对象的回收,但对于深拷贝(深复制)和浅拷贝(浅复制),我们还是要给予足够的重视,因为有时这两个概念往往会给我们带来不小的困惑。

浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。举例来说更加清楚:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2 中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2 中包含对C2(C1的copy)的引用。

若不对clone()方法进行改写,则调用此方法得到的对象即为浅拷贝,下面我们着重谈一下深拷贝。

运行下面的程序,看一看浅拷贝:

 class Professor0 implements Cloneable {
String name;
int age; Professor0(String name, int age) {
this.name = name;
this.age = age;
} public Object clone() throws CloneNotSupportedException {
return super.clone();
}
} class Student0 implements Cloneable {
String name;// 常量对象。
int age;
Professor0 p;// 学生1和学生2的引用值都是一样的。 Student0(String name, int age, Professor0 p) {
this.name = name;
this.age = age;
this.p = p;
} public Object clone() {
Student0 o = null;
try {
o = (Student0) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
} return o;
}
} public class ShallowCopy {
public static void main(String[] args) {
Professor0 p = new Professor0("wangwu", );
Student0 s1 = new Student0("zhangsan", , p);
Student0 s2 = (Student0) s1.clone();
s2.p.name = "lisi";
s2.p.age = ;
s2.name = "z";
s2.age = ;
System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age);// 学生1的教授
}
}

s2变了,但s1也变了,证明s1的p和s2的p指向的是同一个对象。这在我们有的实际需求中,却不是这样,因而我们需要深拷贝:

 class Professor implements Cloneable {
String name;
int age; Professor(String name, int age) {
this.name = name;
this.age = age;
} public Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
return o;
}
} class Student implements Cloneable {
String name;
int age;
Professor p; Student(String name, int age, Professor p) {
this.name = name;
this.age = age;
this.p = p;
} public Object clone() {
Student o = null;
try {
o = (Student) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println(e.toString());
}
o.p = (Professor) p.clone();
return o;
}
} public class DeepCopy {
public static void main(String args[]) {
long t1 = System.currentTimeMillis();
Professor p = new Professor("wangwu", );
Student s1 = new Student("zhangsan", , p);
Student s2 = (Student) s1.clone();
s2.p.name = "lisi";
s2.p.age = ;
System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age);// 学生1的教授不改变。
long t2 = System.currentTimeMillis();
System.out.println(t2-t1);
}
}

当然我们还有一种深拷贝方法,就是将对象串行化:

 import java.io.*;
//Serialization is time-consuming
class Professor2 implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
String name;
int age; Professor2(String name, int age) {
this.name = name;
this.age = age;
}
} class Student2 implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
String name;// 常量对象。
int age;
Professor2 p;// 学生1和学生2的引用值都是一样的。 Student2(String name, int age, Professor2 p) {
this.name = name;
this.age = age;
this.p = p;
} public Object deepClone() throws IOException, OptionalDataException,
ClassNotFoundException {
// 将对象写到流里
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
// 从流里读出来
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (oi.readObject());
} } public class DeepCopy2 { /**
* @param args
*/
public static void main(String[] args) throws OptionalDataException,
IOException, ClassNotFoundException {
long t1 = System.currentTimeMillis();
Professor2 p = new Professor2("wangwu", );
Student2 s1 = new Student2("zhangsan", , p);
Student2 s2 = (Student2) s1.deepClone();
s2.p.name = "lisi";
s2.p.age = ;
System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生1的教授不改变。
long t2 = System.currentTimeMillis();
System.out.println(t2-t1);
} }

但是串行化却很耗时,在一些框架中,我们便可以感受到,它们往往将对象进行串行化后进行传递,耗时较多。

---------------------------------------------------------------------------------------------------------------

注:本文转载于:http://www.cnblogs.com/shuaiwhu/archive/2010/12/14/2065088.html,感谢原文作者!

Java中的深拷贝和浅拷贝(转载)的更多相关文章

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

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

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

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

  3. 内功心法 -- Java中的深拷贝和浅拷贝

    写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------这篇博客主要来谈谈" ...

  4. java中的深拷贝与浅拷贝

    Java中对象的创建 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...

  5. Java中的深拷贝和浅拷贝

    1.浅拷贝与深拷贝概念 (1)浅拷贝(浅克隆) 浅拷贝又叫浅复制,将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段(java中8中原始类型)的值被复制到副本中后,在副本中的修改不会影响到源 ...

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

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

  7. 浅析Java中的深拷贝和浅拷

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

  8. **Python中的深拷贝和浅拷贝详解

    Python中的深拷贝和浅拷贝详解   这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容.   要说清楚Python中的深浅拷贝,需要 ...

  9. C语言中的深拷贝和浅拷贝

    //C语言中的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #inc ...

随机推荐

  1. 吴裕雄 python 机器学习——聚类

    import numpy as np import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import ma ...

  2. UltraFast设计法实践(1) -- 初始设计检查

    目录 1. report_failfast 1.1 命令使用 1.2 优化 1.3.总结 2.report_timing_summary 3. report_methodology 4. 总结 5.遗 ...

  3. python全栈开发_day12_装饰器

    一:装饰器 1)什么是装饰器 装饰器的本质就是利用闭包,在满足开放(修改函数锁包含的功能)封闭(不改变源代码)的情况下完成操作. 2)装饰器的基本运用 def name_judge(f): def a ...

  4. HTTP请求的常用方法有哪些

    HTTP请求的常用方法有:GET方法.POST方法.HEAD方法.PUT方法.DELETE方法.CONNECT方法.OPTIONS方法.TRACE方法.下面本篇文章就给大家介绍具体介绍一下HTTP请求 ...

  5. oracle dump的使用心得

    使用DS开发的时候,有的时候会遇到一个问题:数据库层面定义的空格与DS自已定义的空格概念不一致,导致生成的数据会有一定的问题. 举例来说: 在数据库里面定义CHAR(20),如果插入的字符不足20的时 ...

  6. JDBC(1)-连接数据库

    主要步骤包括: 加载驱动: 连接数据库: 使用语句操作数据库: 关闭数据库连接,释放资源. 1.需要导包: 2.加载数据驱动: mysql驱动名:com.mysql.jdbc.Driver 加载方式: ...

  7. SSL评测

    首先在这个网站上测试一下自己的服务器究竟处于什么水平 https://www.ssllabs.com/ssltest/

  8. twitter storm常用命令

    1.提交Topologies命令格式:storm jar [jar路径] [拓扑包名.拓扑类名][stormIP地址][storm端口][拓扑名称][参数]eg:storm jar /home/sto ...

  9. C 标准库 - string.h之strpbrk使用

    strpbrk Locate characters in string,Returns a pointer to the first occurrence in str1 of any of the ...

  10. TSM简介

    转自:https://www.cnblogs.com/Study-Blog/p/8644376.html Tivoli TSM产品功能详述Tivoli TSM(Tivoli Storage Manag ...