• java笔记关于克隆技术


    关于克隆

    --如果朋友您想转载本文章请注明转载地址"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接口。
    (效率比直接克隆各个引用类型域慢)

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

    知识重在总结和梳理,只有不断地去学习并运用,才能化为自己的东西。由于本人进阶猿类时间尚短,故此博客即是我学习,工作的笔记,也是和大家交流,相互提升技术的平台~希望大家不吝赐教~~ --但管努力,莫问前程,事在人为,功不唐捐。--和佑博客园
  • 相关阅读:
    微信小程序之:获得appid
    小程序v0.10基本布局
    小程序v0.02 清理干净
    微信小程序v0.01
    让Eclipse在10秒内启动的7个优化提速技巧
    转 1 年经验 Java 求职面试题
    坑爹啊
    ES6,时间格式yyyy-MM-dd HH:MM:SS
    ln: creating hard link 问题
    boost实现串口通信(一):小试牛刀
  • 原文地址:https://www.cnblogs.com/XHJT/p/3884817.html
Copyright © 2020-2023  润新知