zoukankan      html  css  js  c++  java
  • Java基础——克隆

    1、克隆

    假设有一个对象object1,在某处又需要一个跟object1一样的实例object2,这两个对象是绝对独立的,不会因为某一个修改另一个随之改变,这样,我们不能直接将对象objec1t的引用赋予object2,object2=object, 这样两个引用仍然指向的是同一个对象,不是两个对象,所以就需要将object1的属性克隆到object2身上

    Java中克隆分为两种,浅克隆和深克隆

    2、浅克隆

    把原型对象中成员变量为值类型的属性都复制给克隆对象,把原型对象中成员变量为引用类型的引用地址也复制给克隆对象

    会复制原型对象,但不会复制它所引用的对象

    浅克隆只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化

    Object类中的clone()方法就是浅克隆

    /**
     * Creates and returns a copy of this object.  The precise meaning
     * of "copy" may depend on the class of the object. The general
     * intent is that, for any object {@code x}, the expression:
     * <blockquote>
     * <pre>
     * x.clone() != x</pre></blockquote>
     * will be true, and that the expression:
     * <blockquote>
     * <pre>
     * x.clone().getClass() == x.getClass()</pre></blockquote>
     * will be {@code true}, but these are not absolute requirements.
     * While it is typically the case that:
     * <blockquote>
     * <pre>
     * x.clone().equals(x)</pre></blockquote>
     * will be {@code true}, this is not an absolute requirement.
     * <p>
     * By convention, the returned object should be obtained by calling
     * {@code super.clone}.  If a class and all of its superclasses (except
     * {@code Object}) obey this convention, it will be the case that
     * {@code x.clone().getClass() == x.getClass()}.
     * <p>
     * By convention, the object returned by this method should be independent
     * of this object (which is being cloned).  To achieve this independence,
     * it may be necessary to modify one or more fields of the object returned
     * by {@code super.clone} before returning it.  Typically, this means
     * copying any mutable objects that comprise the internal "deep structure"
     * of the object being cloned and replacing the references to these
     * objects with references to the copies.  If a class contains only
     * primitive fields or references to immutable objects, then it is usually
     * the case that no fields in the object returned by {@code super.clone}
     * need to be modified.
     * <p>
     * ......
     */
    //Object类中的clone()方法
    protected native Object clone() throws CloneNotSupportedException;

    3、深克隆

    将原型对象中的所有类型,无论是值类型还是引用类型,都复制一份给克隆对象,也就是说深克隆会把原型对象和原型对象所引用的对象,都复制一份给克隆对象

    深克隆是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变

    实现Cloneable接口并重写Object类中的clone()方法或者实现Serializable接口,通过对对象的序列化、反序列化实现克隆和字节流输出,通过这三种方式可以实现深克隆

    Cloneable接口没有任何方法,仅是个标志接口(tagging interface),若要具有克隆能力,实现Cloneable接口的类必须重写从Object继承来的clone方法,并调用Object的clone方法(见下面Object#clone的定义),重写后的方法应为public的

    //Cloneable 接口源码
    public interface Cloneable {
    }
    
    //重写clone()方法
    class CloneClass implements Cloneable{
     
     public Object clone(){
      CloneClass o = null;
      try{
           o = (CloneClass)super.clone();
         CloneClass .setAddress(this.address.clone());//引用克隆类型赋值
    }catch(CloneNotSupportedException e){    
    e.printStackTrace();   
    }   
    return o;  
    }
    }

    如果引用类型中海包括引用类型, 要实现多层克隆会很麻烦, 这使用可以使用序列化和反序列化的方式实现对象的深克隆,把对象写到字节流中的过程是序列化的过程, 而把对象从字节流中读出来的过程是反序列化的过程. 由于Java序列化的过程中, 写在流中的是对象的一个拷贝, 而原对象仍然在JVM中

    public class A implements Serializable {
        private static final long serialVersionUID = "序列化ID";  //显式声明ID
     
        public Outer Aclone() {
            Outer outer = null;
            try { 
            // 将对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(this);
                // 将流序列化成对象
                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bais);
                outer = (Outer) ois.readObject();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return outer;
        }
    }

    通过字节流实现深克隆:

    /**
         * 通过字节流实现克隆
         */
    static class StreamClone {
            public static <T extends Serializable> T clone(People obj) {
                T cloneObj = null;
                try {
                    // 写入字节流
                    ByteArrayOutputStream bo = new ByteArrayOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(bo);
                    oos.writeObject(obj);
                    oos.close();
                    // 分配内存,写入原始对象,生成新对象
                    ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());//获取上面的输出字节流
                    ObjectInputStream oi = new ObjectInputStream(bi);
                    // 返回生成的新对象
                    cloneObj = (T) oi.readObject();
                    oi.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return cloneObj;
            }
        }
  • 相关阅读:
    MarkDownPad 注册码
    ADB server didn't ACK 解决方法
    Python基础教程思维导图笔记
    Java快捷键
    关于chm提示 已取消到该网页的导航的解决方法
    网络基础知识
    将博客搬至CSDN
    hadoop之 yarn (简单了解)
    hadoop之 HDFS 数据I/O(一)
    hadoop 之源码 ResourceManager
  • 原文地址:https://www.cnblogs.com/carblack/p/12906714.html
Copyright © 2011-2022 走看看