美文网首页
2020-02-01浅克隆和深克隆

2020-02-01浅克隆和深克隆

作者: Yangxy_Lazy | 来源:发表于2020-02-01 19:24 被阅读0次

    浅克隆

    • 概念:在浅克隆中,如果原型对象的成员变量是基本数据类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型(类,接口等非基本类型),则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

    • 实现步骤:

        1. 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)
        1. 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象。(native为本地方法)

    深克隆

    • 概念:在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

    • 实现步骤:

      • 实现Clonenable
          1. 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)
          1. 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象,再对对象中的非基本数据类型进行复制。(native为本地方法)
      • 通过序列化(Serialization)等方式:如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆
    public class Outer implements Serializable{
      private static final long serialVersionUID = 369285298572941L;  //最好是显式声明ID
      public Inner inner;
     //Discription:[深度复制方法,需要对象及对象所有的对象属性都实现序列化] 
      public Outer myclone() {
          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;
      }
    }
    
    public class Inner implements Serializable{
      private static final long serialVersionUID = 872390113109L; //最好是显式声明ID
      public String name = "";
    
      public Inner(String name) {
          this.name = name;
      }
    
      @Override
      public String toString() {
          return "Inner的name值为:" + name;
      }
    }
    
    
    注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,
    可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,
    不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。
    让问题在编译的时候暴露出来总是优于把问题留到运行时
    
    

    相关文章

      网友评论

          本文标题:2020-02-01浅克隆和深克隆

          本文链接:https://www.haomeiwen.com/subject/cbmxxhtx.html