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

深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在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 { //实现Cloneable接口,将clone重定义为public,Cloneable只是标记接口,没有具体方法,唯一目的就是用instanceof进行类型检查

    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", 50);

        Student0 s1 = new Student0("zhangsan", 18, p);

        Student0 s2 = (Student0) s1.clone();

        s2.p.name = "lisi";

        s2.p.age = 30;

        s2.name = "z";

        s2.age = 45;

        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", 50);

        Student s1 = new Student("zhangsan", 18, p);

        Student s2 = (Student) s1.clone();

        s2.p.name = "lisi";

        s2.p.age = 30;

        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", 50);

        Student2 s1 = new Student2("zhangsan", 18, p);

        Student2 s2 = (Student2) s1.deepClone();

        s2.p.name = "lisi";

        s2.p.age = 30;

        System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生1的教授不改变。

        long t2 = System.currentTimeMillis();

        System.out.println(t2-t1);

    }

}

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

时间: 2024-10-17 19:44:28

Java中的深拷贝(深复制)和浅拷贝(浅复制)的相关文章

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

深拷贝(深复制)和浅拷贝(浅复制)是两个比较通用的概念,尤其在C++语言中,若不弄懂,则会在delete的时候出问题,但是我们在这幸好用的是Java.虽然java自动管理对象的回收,但对于深拷贝(深复制)和浅拷贝(浅复制),我们还是要给予足够的重视,因为有时这两个概念往往会给我们带来不小的困惑. 浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象.深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象.举例来说更加清楚:对象A1中包含对B1的引用

Java中的深拷贝和浅拷贝

1.浅拷贝与深拷贝概念 (1)浅拷贝(浅克隆) 浅拷贝又叫浅复制,将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段(java中8中原始类型)的值被复制到副本中后,在副本中的修改不会影响到源对象对应的值.而引用类型的字段被复制到副本中的还是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值做修改会影响到源对象本身. 浅拷贝简单归纳就是只复制一个对象,对象内部存在指向其他对象,数组或引用则不复制. (2)深拷贝(深克隆) 将对象中的所有字段复制到新的对象中.不过,无论是对象的值

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

浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: [java] view plaincopyprint? int apples = 5; int pears = apples; int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float

Java中的深拷贝和浅拷贝 原型模式

1: Java中浅拷贝和深拷贝的定义:      浅拷贝:就是指两个对象共同拥有同一个值,一个对象改变了该值,也会影响到另一个对象.      深拷贝:就是两个对象的值相等,但是互相独立. (深拷贝才是真正的拷贝,浅拷贝只是将引用指向了同一份对象) 2:Java中几种常见的拷贝操作: (1)"="操作:也就是赋值操作: (2)拷贝构造函数:拷贝构造函数就是构造函数的参数的类型是该构造函数所在的类,即参数就是该类的一个对象. <span style="font-size:

Java中的clone()----深复制,浅复制

这篇文章主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复制(深克隆) 被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量.那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象.换言之,深复制把要复制的对象所引用

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

假如说你想复制一个简单变量.很简单: [java] view plaincopy int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况. 但是如果你复制的是一个对象,情况就有些复杂了. 假设说我是一个beginner,我会这样写: [java] view plaincopy class Student { private int nu

java中的深拷贝与浅拷贝

Java中对象的创建 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那么在java语言中,有几种方式可以创建对象呢? 1 使用new操作符创建一个对象 2 使用clone方法复制一个对象 那么这两种方式有什么相同和不同呢? new操作符的本意是分配内存.程序执行到new操作符时, 首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间.分配完内存

[clone]Java中的深拷贝和浅拷贝 实例解析

我们平时在开发中经常用到clone这个Object类的方法,但是super.clone()方法所返回的拷贝是浅拷贝,(所谓浅拷贝和深拷贝是相对的,浅拷贝中的内部对象与原始对象的内部对象是共享的,是同一个:而深拷贝中的内部对象也是不同的.),有些情况下,我们需要得到对象的深拷贝,如下面的情况 package day0815; import java.io.File; import java.util.Stack; import org.junit.Test; public class BaseTr

Java中list集合深复制

import org.apache.commons.collections.CollectionUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class CopyTest { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); fo