Java浅拷贝和深拷贝
来源:互联网 发布:网络女主播视频六间房 编辑:程序博客网 时间:2024/06/06 01:31
浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。
深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
举例来说:
对象A1中包含对B1的引用,B1中包含对C1的引用。
浅拷贝对象A1得到A2,A2 中依然包含对B1的引用,B1中依然包含对C1的引用。
深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2 中包含对C2(C1的copy)的引用。
浅拷贝
class Professor implements Cloneable { String name; int age; Professor(String name, int age) { this.name = name; this.age = age; } public Object clone() throws CloneNotSupportedException { return super.clone(); }}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()); } return o; }}public class ShallowCopy { public static void main(String[] args) { Professor p = new Professor("Prof.Chen", 36); Student s1 = new Student("rookie", 18, p); System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age); System.out.println("<------------------------>"); Student s2 = (Student) s1.clone(); s2.p.name = "Prof.Yang"; s2.p.age = 30; s2.name = "newbie"; s2.age = 10; System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age); }}
运行结果是:
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
<————————>
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Yang,
学生s1教授的年纪30
我们发现: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() throws CloneNotSupportedException { return super.clone(); }}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(); // 和ShallowCopy类唯一的变化就是增加了下面这行代码,拷贝对象包含的引用指向的所有对象!!! o.p = (Professor) p.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; }}public class DeepCopy { public static void main(String[] args) { Professor p = new Professor("Prof.Chen", 36); Student s1 = new Student("rookie", 18, p); System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age); System.out.println("<------------------------>"); Student s2 = (Student) s1.clone(); s2.p.name = "Prof.Yang"; s2.p.age = 30; s2.name = "newbie"; s2.age = 10; System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age); }}
运行结果是:
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
<————————>
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
我们发现:s2的修改并未导致s1的同步变化,这就是”深拷贝”,不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象!
利用序列化实现深拷贝
深拷贝一个对象,还可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。应当指出的是,写入流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。代码如下:
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OptionalDataException;import java.io.Serializable;public class DeepCopy implements Serializable { private static final long serialVersionUID = -1889147729394971115L; class Professor implements Serializable { private static final long serialVersionUID = -5461233829245479349L; String name; int age; Professor(String name, int age) { this.name = name; this.age = age; } } class Student implements Serializable { private static final long serialVersionUID = -851210316322914041L; String name; int age; Professor p; Student(String name, int age, Professor 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);// object of student // 从流里读出来 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return (oi.readObject()); } } public static void main(String[] args) { DeepCopy deepCopy = new DeepCopy(); DeepCopy.Professor p = deepCopy.new Professor("Prof.Chen", 36); DeepCopy.Student s1 = deepCopy.new Student("rookie", 18, p); System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age); System.out.println("<------------------------>"); try { Student s2 = (Student) s1.deepClone(); s2.p.name = "Prof.Yang"; s2.p.age = 30; s2.name = "newbie"; s2.age = 10; System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age); } catch (OptionalDataException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
运行结果是:
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
<————————>
学生s1的姓名:rookie
学生s1教授的姓名:Prof.Chen,
学生s1教授的年纪36
我们发现:s2的修改并未导致s1的同步变化,利用序列化也可以实现”深拷贝”!
- Java的深拷贝和浅拷贝
- Java的深拷贝和浅拷贝
- Java中的深拷贝和浅拷贝
- Java的深拷贝和浅拷贝
- Java中的浅拷贝和深拷贝
- java中的深拷贝和浅拷贝
- java浅拷贝和深拷贝
- Java的浅拷贝和深拷贝
- Java的深拷贝和浅拷贝
- Java中的深拷贝和浅拷贝
- Java中的浅拷贝和深拷贝
- Java的深拷贝和浅拷贝
- java 浅拷贝和深拷贝
- Java的深拷贝和浅拷贝
- Java中的深拷贝和浅拷贝
- Java的深拷贝和浅拷贝
- Java的深拷贝和浅拷贝
- Java深拷贝和浅拷贝
- 用jQuery实现三级下拉菜单
- 学习初衷
- Jquery—操作css
- Struts2的工作流程
- loadrunner通过odbc测mysql数据库语句
- Java浅拷贝和深拷贝
- 汇编DEBUG常用指令
- 《深入理解LINUX内核》学习笔记——内存管理
- MFC Windows坐标系统与坐标变换
- Java子父类中的构造函数实例化过程
- 从上往下打印二叉树
- QA、EPG、PMO各自的职能划分及关系是什么?
- Hibernate学习笔记--单表映射
- 王书金:聂案判了,下一个就该我了