关于克隆

--如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3884817.html"谢谢--

1.假克隆
如:
ObjectA objA = new ObjectA();
ObjectB objB = objA;
(对于引用变量而言,使用"="将修改引用,而不是复制堆中的对象,
此时两个引用变量将指向同一个对象,因此,若是一个变量对其进行修改则会改变另外一个变量)
当修改objA时,objB也被修改,故称之为"假克隆"

2.浅克隆
当克隆对象时,需要使用clone()方法:
public Object clone() throws CloneNotSupportedException(默认情况下,该方法实现浅克隆)
由于该方法是受保护的方法,通常需要重写该方法并将访问权限改为public。
该方法将类中各个域进行复制,对于引用类型的域,这种操作会出现问题,故称之为"浅克隆"
提供克隆的类需要实现Cloneable接口,否则使用clone()方法时会抛出CloneNotSupportedException。
@Override
public ObjectA clone(){
ObjectA objA = null;
try{
objA = (ObjectA)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return objA;
}

注意:对于类中的域,如果只包含基本类型和不可变的引用类型,如String,或者对象在其生命周期内不会发生变化,则可以使用浅克隆来复制对象。
3.深克隆
当克隆对象时,需要使用clone()方法:
public Object clone() throws CloneNotSupportedException
(其中ObjectA类是ObjectB类中的一个属性)
@Override
public ObjectB clone(){
ObjectB objB = null;
try{
objB = (ObjectB)super.clone();
objB.objA = objA.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return objB;
}
注意:通常情况下,克隆对象时都需要使用深克隆。但是需要注意的是,如果引用类型中还有可变的引用类型域,
则该域也需要被进行克隆,如上面的ObjectA类如果增加一个X域,则该域也需要被克隆。

4.序列化实现深克隆
对于深克隆而言,如果有很多引用类型的域,那么重写clone()方法一次复制各个域是非常麻烦的,
如果引用类型的域也是由引用类型组成的,则应该考虑使用序列化的方式实现深克隆。
使用序列化写入完成再读出即可实现克隆,此种方法不用考虑引用类型的域,编写clone()方法相对简单,但是要求引用类型也实现Seralizable接口
(若是使用了API中的类且该类并没有实现Seralizable接口,则该域需要使用transient修饰)

ObjectB:
public class ObjectB implements Serializable{
……
@Override
public ObjectB clone(){
ObjectB objB = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try{
//将对象写入到字节数组中
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
oos.close();
}catch(IOException e){
e.printStackTrace();
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
try{
//从字节数组中读取对象
ObjectInputStream ois = new ObjectInputStream(bais);
objB = (ObjectB)ois.readObject();
ois,close();
}catch(IOException e){
e.printStackTrace();
}
return objB;
}
}

对于任何序列化对象,都要求实现Seralizable接口,若是域中有引用类型,则要求该引用类型也实现Seralizable接口。
(效率比直接克隆各个引用类型域慢)

总结:
如果类的各个域是基本类型或不可变类型,则可以使用浅克隆,否则使用深克隆
如果类的域比较复杂,可以使用序列化的方式实现,否则应该使用复制域的方式实现深克隆。

java笔记--关于克隆技术的更多相关文章

  1. golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍

    golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...

  2. JAVA数据库编程(JDBC技术)-入门笔记

    本菜鸟才介入Java,我现在不急着去看那些基本的语法或者一些Java里面的版本的特征或者是一些晋级的知识,因为有一点.Net的OOP编程思想,所以对于Java的这些语法以及什么的在用到的时候在去发现学 ...

  3. java笔记整理

    Java 笔记整理 包含内容     Unix Java 基础, 数据库(Oracle jdbc Hibernate pl/sql), web, JSP, Struts, Ajax Spring, E ...

  4. Java实例 Part6:Java中的克隆

    目录 Part6:Java中的克隆 Example01:Java对象的假克隆 Example02:Java对象的浅克隆 Example03:Java对象的深克隆 Example04:序列化与对象克隆 ...

  5. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  6. Java中如何克隆集合——ArrayList和HashSet深拷贝

    编程人员经常误用各个集合类提供的拷贝构造函数作为克隆List,Set,ArrayList,HashSet或者其他集合实现的方法.需要记住的是,Java集合的拷贝构造函数只提供浅拷贝而不是深拷贝,这意味 ...

  7. Java Web之JSP技术

    JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术.JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比htm ...

  8. Java Web之会话技术

    客户端与服务器通信过程中,会产生一些数据.比如,A和B分别登陆了某宝购物网站,A买了一个Android手机,B买了一个iPhone手机,当结账时,web服务器需要分别对用户A和B的信息分别保存.根据J ...

  9. java笔记00-目录

    --2013年7月26日17:49:59 学习java已久,趁最近有空,写一个总结: java笔记01-反射:

随机推荐

  1. python&MongoDB爬取图书馆借阅记录(没有验证码)

    题外话:这个爬虫本来是想用java完成然后发布在博客园里的,但是一直用java都失败了,最后看到别人用了python,然后自己就找别人问了问关键的知识点,发现连接那部分,python只用了19行!!! ...

  2. java内存优化牛刀小试

    小猿做了两年的c++,上个月竟然被调到java项目,于是第一篇随笔就想八一八java的内存优化. 首先优化这种事,肯定是应该放到最后去做的,不过在写代码的过程中养成良好的习惯也是很重要的.在这里先推荐 ...

  3. WCF入门(10)

    前言 又堕落了,哎. 公司是做乙方的,工资还凑合,主要是项目基本都已完成,进去就是干维护,体会不到那种从头彻尾的成就感.项目中具体用了EF+Ado.net+WCF+WPF+(VB.net啊,坑啊,完全 ...

  4. 【前端开发系列】—— CSS3属性选择器总结

    想想自己为什么要学CSS,作为一个开发过前端的人员来说,调试一个图片花了半天的时间,最后发现分隔符用错了,实在是一件很丢人的事情.因此,痛下决心来学习CSS,最近一周也会更新下相关的学习笔记. CSS ...

  5. c#中的protected和internal

    protected限制子类访问,可以跨程序集 internal 限制此程序集访问,可以跨类 protected internal 限制此程序集的子类中访问

  6. 使用GitHub进行团队合作

    原文: Team Collaboration With GitHub GitHub已经成为的一切开放源码软件的基石.开发人员喜欢它,基于它进行协作,并不断通过它开发令人惊叹的项目.除了​​代码托管,G ...

  7. codevs 1690 开关灯 线段树水题

    没什么好说的,标记put表示开关是否开着. #include<cstdio> #include<cstring> #include<algorithm> using ...

  8. hdu4287 字典树

    #include<stdio.h> #include<string.h> #include<stdlib.h> #define maxn 10 struct tri ...

  9. Date类型时间转换

    /* 时间转换start */ public static void main(String args[]) { Date nowTime = new Date(); System.out.print ...

  10. MyEclipse护眼模式、字体大小的调整

    1.Eclipse改变背景颜色 Windows menu --> Preference General -> Editors -> Text Editors(click),  在底部 ...