`

浅拷贝与深拷贝的实现

 
阅读更多

需要实现对某个对象的拷贝,做了个小例子,便于日后复习。需要拷贝的对象属于Student类型,包含两个字段sex和userName,而userName是属于引用类型。对应的类是Name,该类包含firstName和lastName。代码如下:

   class Name {

       private String firstName ="";

       private String lastName = "";

 

       public void setLastName(String lastName) {

           this.lastName = lastName;

       }

       public String getLastName() {

           return lastName;

       }

       public void setFirstName(String firstName) {

           this.firstName = firstName;

       }

       public String getFirstName() {

           return firstName;

       }

    }

 

   public class Student {

       private String sex = "";

       private Name userName = null;

 

       public void setUserName(Name userName) {

           this.userName = userName;

       }

       public Name getUserName() {

           return userName;

       }

       public void setSex(String sex) {

           this.sex = sex;

       }

       public String getSex() {

           return sex;

       }

   }

当在main方法中写如下代码:

  public static void main(String[] args) throws Exception {

Name name = new Name();

       name.setFirstName("Zhang");

       name.setLastName("San");   

Student student1 = new Student();

       student1.setSex("");

       student1.setUserName(name);

  }

当执行完student1的赋值后,存储的情况大致如下:

 

 

 

需要一个Student类型的对象student2,并且student2从student1复制而来,涉及到两种复制模式,

一是浅拷贝:即将student1的所有的成员变量的值拷贝给student2,但是对于引用类型则是拷贝的地址引用,所有完成浅拷贝后student2与student1中的引用类型的变量userName还是指的同一个对象,当student1的成员变量userName中firstName的值发生改变时,student2的userName中的firstName也会受到影响。浅拷贝后内存中的存储大致如下:

由图容易看出student1与student2对象的userName属性对应的是同一个对象,所有当userName对象中的firstName或是lastName发生改变时,两个对象的对于的属性的值都会受到影响。

第二种拷贝为深拷贝,即对象中的引用类型的变量的值也做拷贝,拷贝后不指向同一对象,这样的话成员变量值的改变互相不会受影响,深拷贝后的内存存储大致如下:

明白了深拷贝与浅拷贝的不同之处后,我们来分别实现两种不同的拷贝。

1,对于浅拷贝可以通过Object对象的clone方法实现。需要被拷贝的对象要实现Cloneable接口,实现clone方法,对应我们的Student类只需要做一些修改即可。public class Student implements Cloneable {

       private String sex = "";

       private Name userName = null;

 

       public void setUserName(Name userName) {

           this.userName = userName;

       }

       public Name getUserName() {

           return userName;

       }

       public void setSex(String sex) {

           this.sex = sex;

       }

       public String getSex() {

           return sex;

       }

      

       @Override

       protected Object clone() throws CloneNotSupportedException {

           return super.clone();

       }

}

 生成studnet1对象后,只需要使用以下语句即可复制生成student2对象:

 Student student2 = (Student)student1.clone();

如果借助apache的beanutils还可以通过以下方式实现浅拷贝

Student student2 = (Student)BeanUtils.cloneBean(student1);

2,对应深拷贝则需要通过序列化的方式实现

 

public class Student implements Cloneable,Serializable {

       private static final long serialVersionUID = 5932252818552269951L;

       private String sex = "";

       private Name userName = null;

       public void setUserName(Name userName) {

           this.userName = userName;

       }

       public Name getUserName() {

           return userName;

       }

       public void setSex(String sex) {

           this.sex = sex;

       }

       public String getSex() {

           return sex;

       }

      

       @Override

       protected Object clone() throws CloneNotSupportedException {

           return super.clone();

       }

      

       public Student deepClone() throws Exception {

           Student s = null;

           ByteArrayOutputStream baos = new ByteArrayOutputStream();

           ObjectOutputStream oos = new ObjectOutputStream(baos);

           oos.writeObject(this);

           oos.flush();

           oos.close();

          

           byte[] arrByte = baos.toByteArray();

           ByteArrayInputStream bais = new ByteArrayInputStream(arrByte);

           ObjectInputStream ois = new ObjectInputStream(bais);

           s = (Student)ois.readObject();

           ois.close();

           return s;

       }

    }

调用deepClone方法就可以实现深拷贝。

Student student2 = student1.deepClone();

可以根据实际的需要选择浅拷贝或是深拷贝。

分类: Java
分享到:
评论

相关推荐

    python浅拷贝、深拷贝

    在Python中,浅拷贝(shallow copy)和深拷贝(deep copy)是用于创建...使用方式:在Python中,可以使用不同的方法实现浅拷贝和深拷贝。例如,对于可变对象,可以使用copy模块的copy函数实现浅拷贝,使用copy.deepco

    JS浅拷贝和深拷贝原理与实现方法分析

    本文实例讲述了JS浅拷贝和深拷贝原理与实现方法。分享给大家供大家参考,具体如下: 浅拷贝只会拷贝一层,深层的引用类型改变还是会受到影响。 深拷贝是所有内部的属性还有值都被拷贝了一份,不管深层的引用类型怎么...

    js浅拷贝与深拷贝的区别和实现方式.md

    js浅拷贝与深拷贝的区别和实现方式.md

    深拷贝浅拷贝.zip

    该例子代码主要实现C#的浅拷贝和深拷贝,深拷贝是通过复制对象和序列化对象两种方法分别实现的。各位同学各取所需。

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

    本文将会深入的探讨一下在拷贝对象中会出现的浅拷贝和深拷贝的情况。 拷贝接口 java中所有的对象都是继承自java.lang.Object。Object对象中提供了一个clone方法,来供我们对java对象进行拷贝。 protected native ...

    JavaScript深拷贝和浅拷贝概念与用法实例分析

    本文实例讲述了JavaScript深拷贝和浅拷贝概念与用法。分享给大家供大家参考,具体如下: js中的浅拷贝和深拷贝,只是针对复杂数据类型(Objcet,Array)的复制问题。简单来讲浅拷贝和深拷贝都可以实现在原有对象的基础...

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

    今天小编就为大家分享一篇关于Java Clone深拷贝与浅拷贝的两种实现方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

    C/C++ 浅拷贝和深拷贝的实例详解

    C/C++ 浅拷贝和深拷贝的实例详解 深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。 浅拷贝就是对内存地址...

    JS中实现浅拷贝和深拷贝的代码详解

    JavaScript的变量中包含两种类型的值:基本类型值 和 引用类型值,这篇文章主要介绍了JS中实现浅拷贝和深拷贝,需要的朋友可以参考下

    前端面试相关-深拷贝和浅拷贝的实现方法和区别

    前端面试相关-深拷贝和浅拷贝的实现方法和区别

    xqddxpy#Web#28-浅拷贝和深拷贝1

    深拷贝会把对象里所有的数据重新复制到新的内存空间,是最彻底的拷贝。浅拷贝的实现方式用 for in 实现浅拷贝(比较繁琐)// 当修改 obj1 的第二层数据时

    js代码-几种实现浅拷贝、深拷贝 方法

    js代码-几种实现浅拷贝、深拷贝 方法

    JavaScript实现浅拷贝与深拷贝的方法分析

    主要介绍了JavaScript实现浅拷贝与深拷贝的方法,结合实例形式总结分析了JavaScript浅拷贝与深拷贝的定义与使用方法,需要的朋友可以参考下

    js中的深拷贝和浅拷贝总结

    1、浅拷贝的实现方式 1.1 Object.assign(target,source)方法 1.2 Array.prototype.concat()方法 1.3 Array.prototype.slice(start,end)方法 2、深拷贝的实现方式 2.1 JSON.parse(JSON.stringify(obj)) 2.2 lodash...

    浅拷贝和深拷贝深入理解(shallow copy VS deep copy)

    引言C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量,对于值类型变量,深拷贝和前拷贝都是通过赋值操作符号(=)实现,其效果一致,将对象中的值类型的字段拷贝到新的对象中.这个很容易理解。 本文重点...

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

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

    详解C++中String类模拟实现以及深拷贝浅拷贝

    详解C++中String类模拟实现以及深拷贝浅拷贝 在C语言中/C++中,字符串是一个应用很广泛的类型,也是很基础的类型,C语言并没有直接处理字符串的操作而是采用字符指针和字符串数组进行操作,而在C++中标准库为我们...

    对浅拷贝、深拷贝、写时拷贝的简单认识

    比如在模拟实现string类时,构造函数中管理了资源,拷贝构造、赋值运算符重载用浅拷贝的方式会导致资源多次释放,也会导致内存泄漏 我们只是将s1的值放到s2中,这样就会导致s1、s2在底层共用同一块内存空间,当出了...

Global site tag (gtag.js) - Google Analytics