`

【转】JAVA深拷贝与浅拷贝

    博客分类:
  • JAVA
阅读更多

深拷贝与浅拷贝的区别
1.浅复制与深复制概念
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,只复制对象的基本类型,对象类型仍属于原来的引用.。

⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,不仅复制对象的基本类,同时也复制原对象中的对象。就是说完全是新对象产生的。

2.Java的clone()方法
⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足:
①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象
②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。

⑵Java中对象的克隆
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone()。
④在派生类中实现Cloneable接口。
请看如下代码:

1 class Student implements Cloneable
2 {
3     String name;
4     int age;
5     Student(String name,int age)
6     {
7        this.name=name;
8        this.age=age;
9     }
10     public Object clone()
11     {
12        Object o=null;
13        try
14        {
15          o=(Student)super.clone();//Object中的clone()识别出你要复制的是哪一个对象。
16         }
17        catch(CloneNotSupportedException e)
18        {
19          System.out.println(e.toString());
20        }
21        return o;
22      }
23
24
25     public static void main(String[] args)
26     {
27        Student s1=new Student("zhangsan",18);
28        Student s2=(Student)s1.clone();
29        s2.name="lisi";
30        s2.age=20;
31        System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2后,不影响学生1的值。                                                                                                    
32      }
33 }
说明:
①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。

1 class Professor implements Cloneable
2 {
3      String name;
4      int age;
5      Professor(String name,int age)
6      {
7         this.name=name;
8         this.age=age;
9      }
10      public Object clone() throws CloneNotSupportedException{
11       return super.clone();
12      }
13 }
14  class Students implements Cloneable
15 {
16      String name;     //常量对象。
17       int age;
18      Professor p;      //学生1和学生2的引用值都是一样的。
19       Students(String name,int age,Professor p)
20      {
21         this.name=name;
22         this.age=age;
23         this.p=p;
24      }
25      public Object clone()
26      {
27          Students o=null;
28          try
29          {
30              o=(Students)super.clone();
31              o.p=(Professor)p.clone();
32          }
33          catch(CloneNotSupportedException e)
34          {
35              System.out.println(e.toString());
36          }
37       
38         return o;
39      }
40
41    public static void main(String[] args)
42  {
43        Professor p=new Professor("wanGWu",50);
44        Students s1=new Students("zhangsan",18,p);
45        Students s2=(Students)s1.clone();
46        s2.p.name="lisi";
47       s2.p.age=30;
48       System.out.println("name="+s1.p.name+","+"age="+s1.p.age);//学生1的教授成为lisi,age为30。                                                                                                            
49    }
50 }

那应该如何实现深层次的克隆,即修改s2的教授不会影响s1的教授?代码改进如下。

改进使学生1的Professor不改变(深层次的克隆)


1 class Professor implements Cloneable
2 {
3      String name;
4      int age;
5      Professor(String name,int age)
6      {
7         this.name=name;
8         this.age=age;
9      }
10      public Object clone()
11      {
12          Object o=null;
13          try
14          {
15              o=super.clone();
16          }
17          catch(CloneNotSupportedException e)
18          {
19              System.out.println(e.toString());
20          }
21         return o;
22      }
23 }
24  class Student implements Cloneable
25 {
26      String name;
27      int age;
28      Professor p;
29      Student(String name,int age,Professor p)
30      {
31         this.name=name;
32         this.age=age;
33         this.p=p;
34      }
35      public Object clone()
36      {
37          Student o=null;
38          try
39          {
40              o=(Student)super.clone();
41          }
42          catch(CloneNotSupportedException e)
43          {
44              System.out.println(e.toString());
45          }
46          o.p=(Professor)p.clone();
47          return o;
48      }
49
50     public static void main(String[] args)
51   {
52        Professor p=new Professor("wangwu",50);
53        Student s1=new Student("zhangsan",18,p);
54        Student s2=(Student)s1.clone();
55        s2.p.name="lisi";
56       s2.p.age=30;
57       System.out.println("name="+s1.p.name+","+"age="+s1.p.age);   //学生1的教授不改变。
58     }
59 }

3.利用串行化来做深复制
把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
如下为深复制源代码。

1 public Object deepClone() throws IOException, ClassNotFoundException
2 {
3  //将对象写到流里
4   ByteArrayOutputStream bo=new ByteArrayOutputStream();
5  ObjectOutputStream oo=new ObjectOutputStream(bo);
6  oo.writeObject(this);
7  //从流里读出来
8   ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
9  ObjectInputStream oi=new ObjectInputStream(bi);
10  return(oi.readObject());
11 }

这样做的前提是对象以及对象内部所有引用到的对象都是可串行化的,否则,就需要仔细考察那些不可串行化的对象可否设成transient,从而将之排除在复制过程之外。上例代码改进如下。
1 class Professor implements Serializable{
2      String name;
3     int age;
4      Professor(String name,int age)
5      {
6         this.name=name;
7         this.age=age;
8      }
9 }
10  class Student implements Serializable
11 {
12      String name;//常量对象。
13      int age;
14      Professor p;//学生1和学生2的引用值都是一样的。
15       Student(String name,int age,Professor p)
16      {
17         this.name=name;
18         this.age=age;
19         this.p=p;
20      }
21  public Object deepClone() throws IOException,OptionalDataException,ClassNotFoundException{
22   //将对象写到流里
23    ByteArrayOutputStream bo=new ByteArrayOutputStream();
24   ObjectOutputStream oo=new ObjectOutputStream(bo);
25   oo.writeObject(this);
26   //从流里读出来
27    ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
28   ObjectInputStream oi=new ObjectInputStream(bi);
29   return(oi.readObject());
30 }
31
32
33  public static void main(String[] args) throws OptionalDataException, IOException, ClassNotFoundException
34      {
35        Professor p=new Professor("wangwu",50);
36        Student s1=new Student("zhangsan",18,p);
37        Student s2=(Student)s1.deepClone();
38        s2.p.name="lisi";
39       s2.p.age=30;
40       System.out.println("name="+s1.p.name+","+"age="+s1.p.age); //学生1的教授不改变。
41       }
42 }

 

分享到:
评论

相关推荐

    Java Clone深拷贝与浅拷贝的两种实现方法

    Java Clone 深拷贝与浅拷贝的两种实现方法 Java Clone 是 Java 语言中的一种复制对象的机制,它可以将一个对象的所有属性和状态复制到另一个对象中,实现对象的深拷贝和浅拷贝。下面我们将讨论 Java 中的深拷贝和浅...

    Java中的深拷贝(深复制)和浅拷贝(浅复制) 示例代码

    为了理解深拷贝(深复制)和浅拷贝(浅复制),我们需要首先了解Java对象内存的分配方式以及引用的概念。 1. **对象复制的基础** 在Java中,当我们创建一个对象时,系统会在内存中为该对象分配一块空间,存储它的...

    Java中的深拷贝(深复制)和浅拷贝(浅复制)介绍

    在Java编程语言中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是两种不同的对象复制方式,它们涉及到内存中数据的复制和引用的处理。理解这两种拷贝方式对于开发过程中正确管理和操作对象至关重要。 浅拷贝,又...

    浅析Java中的深拷贝与浅拷贝

    首先我们看看浅拷贝和深拷贝的定义 浅拷贝:只复制一个对象,对象内部存在的指向其他对象数组或者引用则不复制 深拷贝:对象,对象内部的引用均复制 为了更好的理解它们的区别我们假设有一个对象A,它包含...

    java深入理解浅拷贝和深拷贝

    在Java编程中,深入理解浅拷贝和深拷贝是非常重要的概念,特别是在处理对象复制时。浅拷贝和深拷贝的区别在于复制对象时对内存中数据的处理方式。 浅拷贝(Shallow Copy)指的是创建一个新的对象,该对象与原对象...

    深拷贝拷贝的是内容,浅拷贝拷贝的是指针

    ### 深拷贝与浅拷贝的概念及应用 #### 一、深拷贝与浅拷贝的区别 在计算机编程领域中,深拷贝(Deep Copy)与浅拷贝(Shallow Copy)是两种常见的对象复制方法。这两种方法在处理复杂数据结构(如数组、列表等)时...

    Java 浅拷贝性能比较完整源码

    在Java编程中,对象的复制是一个常见的操作,主要分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。本篇文章将详细讲解Java中的浅拷贝,并通过一个完整的源码示例进行性能比较。 浅拷贝是创建一个新的对象,然后...

    使用java反射机制实现java的深拷贝

    在Java编程中,深拷贝和浅拷贝是两种常见的对象拷贝方式。它们主要区别在于,浅拷贝仅复制对象本身,而不复制它引用的对象;而深拷贝则会递归地复制对象及其所有引用的对象。在某些情况下,如需要完全独立的副本时,...

    java对象的深拷贝和浅拷贝[归类].pdf

    4. **浅拷贝与深拷贝示例**: 在给出的例子中,我们有两个测试类`Test2`和`Test3`,分别演示了浅拷贝和深拷贝的效果。 - 在`Test2`中,通过简单赋值创建了一个新的`Test`对象`t2`,这是浅拷贝。当修改`t2`的属性时...

    java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】

    java设计模式【之】原型模式、深拷贝与浅拷贝【源码】【场景:克隆羊】 * 原型模式(Prototype) * 实现方式: * 需要被克隆的 class类, 重写Object中的clone()方法,并实现Cloneable接口(否则报错 ...

    《剑指offer》Java浅拷贝和深拷贝.pdf

    在Java中,对象拷贝分为两种主要类型:浅拷贝(Shallow Copy)和深拷贝(Deep Copy)。这两种拷贝方式主要区别在于如何处理对象中的引用数据类型。 首先,让我们理解Java中的引用。在Java中,基础数据类型(如int、...

    Java 细数浅拷贝和深拷贝

    在Java开发中,理解和掌握浅拷贝与深拷贝的概念及其实现方式是非常重要的。它们不仅关乎对象的内存管理和生命周期,也是解决复杂对象管理问题的基础。根据具体情况选择合适的拷贝策略,有助于提高程序的性能和维护性...

    java List 深度复制方法

    当我们需要复制一个List时,可能会遇到浅复制和深复制的概念。浅复制只复制对象本身,而不复制它引用的对象,而深复制则会递归复制所有引用的对象。这篇博客将探讨如何在Java中对List进行深度复制。 首先,我们来...

    java 深拷贝与浅拷贝机制详解

    了解和掌握深拷贝与浅拷贝的概念以及如何在Java中实现它们,对于编写高效、健壮的代码至关重要,尤其是在处理复杂的对象结构和数据时。正确地使用拷贝机制可以帮助我们避免不必要的副作用,并确保程序的正确性。

    java值拷贝

    这个主题涉及到Java中的浅拷贝和深拷贝概念,以及如何利用工具库如Apache Commons BeanUtils进行对象属性的便捷复制。 Apache Commons BeanUtils是一个非常实用的Java库,它提供了一系列方法来简化JavaBean的操作,...

    浅拷贝(浅复制、浅克隆)、深拷贝(深复制、深克隆)实战工程

    总之,理解和掌握浅拷贝与深拷贝的概念及其实现方法,对于优化代码性能、防止意外数据修改以及提升程序的健壮性至关重要。在开发过程中,应根据实际情况选择合适的方式进行对象复制,以满足业务需求。

    什么是深拷贝、浅拷贝,什么是引用拷贝

    什么是深拷贝、浅拷贝,什么是引用拷贝。

    android 浅复制和深复制-Java Generic Deep Copy 篇

    本文将深入探讨Java中的浅复制和深复制,并以Android为背景,结合具体的实例讲解如何实现Java泛型深拷贝。 首先,我们要理解浅复制和深复制的概念。浅复制(Shallow Copy)是指创建一个新的对象,然后将原对象引用...

    浅谈Java中实现深拷贝的两种方式—clone() & Serialized

    Java中实现深拷贝的两种方式—clone() & Serialized 在Java中,实现深拷贝是一种常见的需求,特别是在对象之间存在多层次关系的情况下。深拷贝可以帮助我们在对象之间保持独立性,并避免了对象之间的耦合关系。在...

Global site tag (gtag.js) - Google Analytics