java中对象的深拷贝和浅拷贝

根据对象成员变量的拷贝程度(基本数据类型、引用类型),可将拷贝分为浅拷贝和深拷贝。

一、浅拷贝

package javaKeyTechnology;

class PerSon{
    private String name;
    private int age;
    PerSon(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void setName(String name){ //私有数据的更改器
        this.name = name;
    }

    public String getName(){ //私有数据的访问器
        return name;
    }

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

    public int getAge(){
        return age;
    }

    public String toString(){
        return "Person:["+this.hashCode()+" name:"+name+" age:"+age+"]";
    }

}
public class MyClone implements Cloneable{
    PerSon man;
    private int id;
    private String gender;

    public MyClone(String name,int age,String gender,int id){
        man = new PerSon(name,age);
        this.gender = gender;
        this.id = id;
    }
    public void setId(int id){
        this.id = id;
    }

    public int getId(){
        return id;
    }

    public void setGender(String gender){
        this.gender = gender;
    }

    public String getGender(){
        return gender;
    }
    public String toString(){
        return man.toString() + this.hashCode() + " gender:"+gender+" id:"+id;
    }

    //浅拷贝
    public MyClone clone(){
        try {
            return (MyClone)super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

    public static void main(String[] args){
        MyClone student1 = new MyClone("LiLi",16,"felman",123456);
        MyClone student2 = student1.clone();
        MyClone student3 = student1;
        student2.man.setAge(20);//改变student的引用变量的内容
        student2.man.setName("Jason");
        student2.setId(888888);//改变student的基本类型变量的内容
        student2.setGender("man");
        System.out.println("浅拷贝");
        System.out.println("student1:        " + student1.toString());
        System.out.println("student1.clone   " + student2.toString());
        System.out.println("对象拷贝");
        System.out.println("student1.copy:   " + student1.toString());
    }
}

可见,对于浅拷贝:

1.创建了新对象,和原对象的hashcode不同;

2.成员变量中的基本数据类型是是拷贝其值,新对象和原对象中任一对象的基本数据类型发生改变,对另一对象不产生影响。所以原对象的id没有改变。

3.成员变量中的不可变对象的引用类型(如String),虽然是拷贝其地址,由于其引用的对象不可变,改变新对象和原对象任一的该变量(引用),只是让它引用了新的不可变对象,另外一个对象的该变量所引用的对象不变。所以原对象的gender没有改变。

4.成员变量中的可变对象的引用类型是是拷贝地址。新对象和原对象中该变量指向同一对象,所以person的hashCode相同;任一对象的该引用的对象内容发生改变,对另一对象产生影响,所以原对象的person内容也改变了。

5.Object.clone()是浅拷贝,如果在实现了Cloneable接口后只调用Object.clone(),自然也只能是浅拷贝。

对于浅拷贝和对象拷贝的区别:

1.浅拷贝创建了新对象,两对象地址不同。

2.对象拷贝没有创建新对象,两个变量指向的是同一个对象,同一个地址。

二、深拷贝

package javaKeyTechnology;

class PerSon implements Cloneable{
    private String name;
    private int age;
    PerSon(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void setName(String name){ //私有数据的更改器
        this.name = name;
    }

    public String getName(){ //私有数据的访问器
        return name;
    }

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

    public int getAge(){
        return age;
    }

    public String toString(){
        return "Person:["+this.hashCode()+" name:"+name+" age:"+age+"]";
    }

    public PerSon clone(){
        try {
            return (PerSon)super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

}
public class MyClone implements Cloneable{
    PerSon man;
    private int id;
    private String gender;

    public MyClone(String name,int age,String gender,int id){
        man = new PerSon(name,age);
        this.gender = gender;
        this.id = id;
    }
    public void setId(int id){
        this.id = id;
    }

    public int getId(){
        return id;
    }

    public void setGender(String gender){
        this.gender = gender;
    }

    public String getGender(){
        return gender;
    }
    public String toString(){
        return man.toString() + this.hashCode() + " gender:"+gender+" id:"+id;
    }

    //深拷贝
    public MyClone clone(){
        try {
            MyClone tmp = (MyClone)super.clone();
            tmp.man = man.clone(); //把现在对象的man克隆
            return tmp;
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

    public static void main(String[] args){
        MyClone student1 = new MyClone("LiLi",16,"felman",123456);
        MyClone student2 = student1.clone();
        student2.man.setAge(20);//改变student的引用变量的内容
        student2.man.setName("Jason");
        student2.setId(888888);//改变student的基本类型变量的内容
        student2.setGender("man");
        System.out.println("深拷贝");
        System.out.println("student1:        " + student1.toString());
        System.out.println("student1.clone   " + student2.toString());

    }
}

原对象和拷贝后创建的新对象中任一对象的任意成员变量(基本数据类型、不可变对象的引用、可变对象的引用)发生改变,都不影响另一个对象的成员变量。

深拷贝比浅拷贝多做的工作是:让新对象的引用变量 = 该引用所指对象的深拷贝

如果对象有多层对象(成员变量是引用),每层对象所属的类都要实现Cloneable接口并重写clone()。如果类的超类是Object,直接重写clone()。

原文地址:https://www.cnblogs.com/leechee9/p/11982787.html

时间: 2024-10-13 13:51:18

java中对象的深拷贝和浅拷贝的相关文章

PHP中对象的深拷贝与浅拷贝

先说一下深拷贝和浅拷贝通俗理解 深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个 浅拷贝:赋值时,引用赋值,相当于取了一个别名.对其中一个修改,会影响另一个 PHP中, = 赋值时,普通对象是深拷贝,但对对象来说,是浅拷贝.也就是说,对象的赋值是引用赋值.(对象作为参数传递时,也是引用传递,无论函数定义时参数前面是否有&符号) <?php //普通对象赋值,深拷贝,完全值复制 $m = 1; $n = $m; $n = 2; echo $m;//值复制,对新对象的

探究JS中对象的深拷贝和浅拷贝

深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj1; testObj1.a = 7; console.log(testObj1); //{a: 7, b:2} console.log(testObj2); //{a: 7, b:2} 发现问题了吗?当testObj1变化时,testObj2相应的属性跟着变化了.这就是属于浅拷贝了,而所谓的深拷贝就

Java中对象、对象引用、堆、栈、值传递以及引用传递的详细解释

Java中对象.对象引用.堆.栈.值传递以及引用传递的详细解释 1.对象和对象引用的区别: (1).对象: 万物皆对象.对象是类的实例.在Java中new是用来在堆上创建对象用的.一个对象可以被多个引用所指向. (2).对象引用: 类似于C++中的地址.通过对象引用可以找到对象.一个引用可以指向多个对象.操纵的标识符实际上是指向对象的引用. 就像:对象存放在屋子里,对象的引用就相当于屋子的钥匙. 2.值传递和引用传递的区别: (1).值传递:传递的是值的拷贝.也就是说传递后就不互相关了. (2)

java中对象多态时成员变量,普通成员函数及静态成员函数的调用情况

/* 样例1: class Parent{ int num = 3; } class Child extends Parent{ int num = 4; } */ /* 样例2: class Parent{ } class Child extends Parent{ int num = 4; } */ /* 样例3: class Parent{ void show(){ System.out.println("Parent Show!"); } } class Child exten

java中对象的初始化过程

class Parent{ int num = 8;// ->3 Parent(){ //super(); // ->2 //显示初始化 // ->3 //构造代码段 // ->4 show(); // ->5 } {// ->4 System.out.println("Parent constructor code run->"); } public void show(){//被覆盖 System.out.println("num

JAVA中对象的克隆及深拷贝和浅拷贝

使用场景: 在日常的编程过程 中,经常会遇到,有一个对象OA,在某一时间点OA中已经包含了一些有效值 ,此时可能会需一个和OA完全相对的新对象OB,并且要在后面的操作中对OB的任何改动都不会影响到OA的值,也就是OA与Ob是需要完全两个独立的对象. 但OB的初始值是由对象OA确定的.在JAVA语言中,用普通的赋值语句是满足不了需求的.使用对象的clone()方法是实现克隆的最简单.也是最高效的手段. Java的所有类都默认继承java.lang.Object类,在java.lang.Object

Java中的clone() 深拷贝 浅拷贝

上图展示了浅拷贝:对于非基本数据类型,clone过后,结果两个指针指向了同一块儿内存空间,所以仅仅是浅拷贝,这样的话如果对一个对象进行操作,另一个内容也会变,这显然是不合理的,应该每个对象分别保存自己的数据. 所以我们要进行深拷贝! 浅拷贝和深拷贝例子: import java.util.Vector; public class Student implements Cloneable{ private int id; private String name; private Vector co

C#对象的深拷贝与浅拷贝

转载自:http://blog.163.com/hr_msn/blog/static/21549405120132250396584/ 深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响.举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人.比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等. 考虑以下写法 in

js 中引用类型 的深拷贝 和 浅拷贝的区别

一.曾经在读JQ源码的时候,对深拷贝算是有了一点的理解.我们在项目中是不是经常会遇到这样的问题呢? 后台返回一个数组对象(引用类型).次数在页面渲染中需要对部分数据进行处理 比如:银行卡62345092534 (这么长) 但在页面显示的时候, 只显示中国银行(3118)但是传给后台的时候.又要传623445242整个号码,我们也许会把var oldData = res.data; 但是我们发现两个数据都变了? 这是为什么呢? 其实就是一个深浅拷贝的问题. 二.浅拷贝 比如数组,对象,这样的引用类