惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
GbyAI
GbyAI
博客园_首页
V
Visual Studio Blog
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 叶小钗
腾讯CDC
博客园 - Franky
IT之家
IT之家
Google DeepMind News
Google DeepMind News
Microsoft Azure Blog
Microsoft Azure Blog
D
Docker
大猫的无限游戏
大猫的无限游戏
Recent Announcements
Recent Announcements
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
B
Blog
酷 壳 – CoolShell
酷 壳 – CoolShell

博客园 - 龚明秋

JavaScript获取客户端IP和MAC地址 java实现算术表达式求值 包含中文的字符串截取 Table动态增加删除行 Java批量下载生成zip文件 JavaScript校验日期格式 使用过滤器来处理Session超时和权限管理 jsp页面内容导出到Excel中 - 龚明秋 - 博客园 Java读取Excel内容 Excel中如何根据身份证号码获取年龄,性别 坦克大战游戏-Java版 Java实现的简易文本编辑器 VB.NET实现的文本编辑器 串的模式匹配算法之二:首尾匹配算法 串的模式匹配算法之一:简单算法 Union Two Lists 有趣的猜数字游戏 用C#实现的简易计算器 用C#实现约瑟夫问题
浅拷贝与深拷贝的实现 - 龚明秋 - 博客园
龚明秋 · 2010-05-30 · via 博客园 - 龚明秋

需要实现对某个对象的拷贝,做了个小例子,便于日后复习。需要拷贝的对象属于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();

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