java浅拷贝和深拷贝(基础也是很重要的)

对象的copy你兴许只是懵懂,或者是并没在意,来了解下吧。

对于的github基础代码https://github.com/chywx/JavaSE

最近学习c++,跟java很是相像,在慕课网学习c++也算是重温习了下java基础

明白了当初讲师一直强调java传递的话只有值传递,不存在引用传递,为什么一直要重复这,既然只有值传递,为啥还强调不是引用传递

毛病啊这是

学了c++才知道,原来c++有值传递,引用传递的说法,但是java只是值传递

最简单的理解就是对于方法调用

比如 f(int a,int b) 这是值传递,传递过来的值不会被修改。

再如 f(int &a,int &b)这是引用传递,传递过来的值会被修改

步入正轨,说一说java的浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。

浅拷贝(Shallow Copy):①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

通过示例来了解下,

一:

  使用构造函数实现copy

public class Person {
    public static void main(String[] args) {
        Son s = new Son(10);
        Person p1 = new Person("大海", s);
        Person p2 = new Person(p1);
        p1.setSonName("小海");
        p1.getSon().setAge(12);
        System.out.println("p1:" + p1);// p1:Person [sonName=小海, son=Son [age=10]]
        System.out.println("p2:" + p2);// p2:Person [sonName=大海, son=Son [age=10]]

    }

    private String sonName;
    private Son son;

    // 自定义拷贝函数
    public Person(Person person) {
        this.sonName = person.sonName;
        this.son = person.son;
    }

    public Person(String sonName, Son son) {
        super();
        this.sonName = sonName;
        this.son = son;
    }

    public String getSonName() {
        return sonName;
    }

    public void setSonName(String sonName) {
        this.sonName = sonName;
    }

    public Son getSon() {
        return son;
    }

    public void setSon(Son son) {
        this.son = son;
    }

    @Override
    public String toString() {
        return "Person [sonName=" + sonName + ", son=" + son + "]";
    }

}

class Son {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Son(int age) {
        super();
        this.age = age;
    }

    @Override
    public String toString() {
        return "Son [age=" + age + "]";
    }

}

结果

p1:Person [sonName=小海, son=Son [age=12]]
p2:Person [sonName=大海, son=Son [age=12]]

对于上面的实例,该person对象有两个成员,一个基本类型,一个引用类型,结果是拷贝出来的对象,基本类型的那个成员真正的实现了copy。

二:

  使用自带的clone方法,需要实现cloneable接口,不然会

Exception in thread "main" java.lang.CloneNotSupportedException:

public class Person2 implements Cloneable {
    public static void main(String[] args) throws CloneNotSupportedException {
        Son2 son1 = new Son2(10);

        Person2 person1 = new Person2("大海", son1);
        Person2 person2 = (Person2) person1.clone();
        person2.setSon2Name("小海");
        person2.getSon2().setAge(12);
        System.out.println(person1);
        System.out.println(person2);
    }

    public Person2(String son2Name, Son2 son2) {
        super();
        this.son2Name = son2Name;
        this.son2 = son2;
    }

    private String son2Name;
    private Son2 son2;

    public String getSon2Name() {
        return son2Name;
    }

    public void setSon2Name(String son2Name) {
        this.son2Name = son2Name;
    }

    public Son2 getSon2() {
        return son2;
    }

    public void setSon2(Son2 son2) {
        this.son2 = son2;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Person2 [son2Name=" + son2Name + ", son2=" + son2 + "]";
    }

}

class Son2 {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Son2 [age=" + age + "]";
    }

    public Son2(int age) {
        super();
        this.age = age;
    }

}

结果:

Person2 [son2Name=大海, son2=Son2 [age=12]]
Person2 [son2Name=小海, son2=Son2 [age=12]]

使用自带的copy实现浅拷贝

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

深拷贝

  相对于浅拷贝而言,对于引用类型的修改,并不会影响到对应的copy对象的值。每一层的每个对象都进行浅拷贝=深拷贝。

一:

  还是使用clone方法,只不过得手动重写一下。

上代码

public class Person3 implements Cloneable {
    public static void main(String[] args) throws CloneNotSupportedException {
        Son3 son1 = new Son3(10);
        Person3 person1 = new Person3("大海", son1);
        Person3 person2 = (Person3) person1.clone();
        person2.setSon2Name("小海");
        person2.getSon3().setAge(12);//修改对应的引用对象的值。
        System.out.println(person1);
        System.out.println(person2);
    }

    public Person3(String son2Name, Son3 son3) {
        super();
        this.son2Name = son2Name;
        this.son3 = son3;
    }

    private String son2Name;
    private Son3 son3;

    public String getSon2Name() {
        return son2Name;
    }

    public void setSon2Name(String son2Name) {
        this.son2Name = son2Name;
    }

    public Son3 getSon3() {
        return son3;
    }

    public void setSon3(Son3 son3) {
        this.son3 = son3;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person3 clone = (Person3) super.clone();
        clone.setSon3((Son3) clone.getSon3().clone());
        return clone;
    }

    @Override
    public String toString() {
        return "Person3 [son2Name=" + son2Name + ", son3=" + son3 + "]";
    }

}

class Son3 implements Cloneable {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Son2 [age=" + age + "]";
    }

    public Son3(int age) {
        super();
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

结果:

Person3 [son2Name=大海, son3=Son2 [age=10]]

Person3 [son2Name=小海, son3=Son2 [age=12]]

方法二:

  显然对于多个对象的话,显然就很吃力。可以使用另一种方式,

  将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。

public class Person4 implements Serializable {
    public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException {
        Son4 son = new Son4(10);
        Person4 person1 = new Person4("大海", son);
        //通过序列化方法实现深拷贝
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(person1);
        oos.flush();
        ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        Person4 person2=(Person4)ois.readObject();
        person1.setSon4Name("小海");
        person1.getSon4().setAge(12);
        System.out.println(person1.toString());
        System.out.println(person2.toString());
    }

    public Person4(String son4Name, Son4 son4) {
        super();
        this.son4Name = son4Name;
        this.son4 = son4;
    }

    private String son4Name;
    private Son4 son4;

    public String getSon4Name() {
        return son4Name;
    }

    public void setSon4Name(String son4Name) {
        this.son4Name = son4Name;
    }

    public Son4 getSon4() {
        return son4;
    }

    public void setSon4(Son4 son4) {
        this.son4 = son4;
    }

    @Override
    public String toString() {
        return "Person4 [son4Name=" + son4Name + ", son4=" + son4 + "]";
    }
}

class Son4 implements Serializable {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Son2 [age=" + age + "]";
    }

    public Son4(int age) {
        super();
        this.age = age;
    }

}

这是实现序列化接口方案,nice.

perfect!!!到位

原文地址:https://www.cnblogs.com/c-h-y/p/9574586.html

时间: 2024-10-13 16:32:44

java浅拷贝和深拷贝(基础也是很重要的)的相关文章

Java 浅拷贝,深拷贝

从Java 强引用,软引用,弱引用http://blog.csdn.net/jltxgcy/article/details/35558465一文中,我们看到把一个对象赋值给另一个对象,本质上是增加了引用计数,但是它们都指向同样的堆内存,它们是一个对象.如果我们想要一个独立的对象,改怎么办呢?答案是clone. 1.浅拷贝 浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象. ShallowCopy.java class Professor0 imple

浅谈java浅拷贝和深拷贝

前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.深拷贝:被复制对象的所有变量都含有与原来对象相同的值,而那些引用对象的变量将指向被复制过的新对象,而不再是原有 的那些被引用的对象.换言之,深拷贝把要复制的对象所引用的对象都复制了一遍. 浅拷贝 浅拷贝对于基本数据类型进行的是值传递,而对引用数据类型进行的是引用传递.无论是浅拷贝还是深拷贝都要用到clo

Java 浅拷贝和深拷贝

一看就懂的,java深拷贝浅拷贝 将一个对象的引用复制给另外一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式是浅拷贝,第三种是深拷贝.所以大家知道了哈,这三种概念实际上都是为了拷贝对象啊. 1.直接赋值 好,下面我们先看第一种方式,直接赋值.在Java中,A a1 = a2,我们需要理解的是这实际上复制的是引用,也就是说a1和a2指向的是同一个对象.因此,当a1变化的时候,a2里面的成员变量也会跟着变化.各位,请看下面的代码吧! /* 建立类 */ class Resume { pri

java浅拷贝与深拷贝详解

/** * @author MaskedMen *java深克隆与浅克隆讲解 *技术交流群:JAVA/WEB/安卓精英群 316278345 *联系邮箱:[email protected] */ public class CloneDemo { public static void main(String[] args) { Person maskedmen1 = new Person("maskedmen1",20); Fruit watermelon = new Fruit(&qu

浅谈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中的深拷贝与浅拷贝

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

Java的浅拷贝与深拷贝总结

Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去.举例说明:比如,对象A和对象B都属于类S,具有属性a和b.那么对对象A进行拷贝操作赋值给对象B就是:B.a=A.a;  B.b=A.b; 在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用现有对象的部分或全部 数据. Java中的对象拷贝主要分为:浅拷贝(Shallow Copy).深拷贝(Deep Copy). 先介绍一点铺垫知识:Java中的数据类型分为基本数据

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

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

Java中的深拷贝和浅拷贝

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