对象克隆


        Teacher teacher = new Teacher();
        Teacher cloneTea = teacher;
        cloneTea.setSalary(3000);
        System.out.println("teacher: "+teacher);
        System.out.println("cloneTea: "+cloneTea);
teacher: Teacher{salary=3000}
cloneTea: Teacher{salary=3000}
//Teacher cloneTea = teacher这句话只是将引用赋值

1. 浅克隆。

  • 浅克隆:只复制基本类型的数据,引用类型的数据只复制了引用的地址
  • 实现 : 被复制的类实现Clonenable接口,覆盖clone()方法
    `java
    public class Student implements Cloneable {//实现Cloneable接口
    private Integer number;

    /* 重写clone方法(Object里clone方法是protect修饰的)

    • */
      @Override
      public Object clone() {
      Student student = null;
      try {
       student = (Student) super.clone();
      
      } catch (CloneNotSupportedException e) {
       e.printStackTrace();
      
      }
      return student;
      }
      }
public static void main(String[] args) {
    Student student1 = new Student();
    student1.setNumber(200);
    Student student2 = (Student) student1.clone();
    System.out.println(student1==student2);
    System.out.println("student1:" + student1);
    System.out.println("student2:" + student2);
    student2.setNumber(500);
    System.out.println("student1:" + student1);
    System.out.println("student2:" + student2);
}
```java
false//地址不一样了哦
student1:Student{number=200}
student2:Student{number=200}
student1:Student{number=200}
student2:Student{number=500}

但是如果Student类的属性是另外一个类的话,就会出现新的问题

    public static void main(String[] args) {
        Teacher teacher = new Teacher("武昌");
        Student student1 = new Student();
        student1.setTeacher(teacher);
        Student student2 = (Student) student1.clone();
        System.out.println(student1 == student2);
        System.out.println("student1:" + student1);
        System.out.println("student2:" + student2);
        student2.getTeacher().setAddress("江夏");
        System.out.println("student1:" + student1);
        System.out.println("student2:" + student2);
    }
false
student1:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student1:Student{number=null, teacher=Teacher{salary=null, address='江夏'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='江夏'}}

可以看到两个address都变了
稍微修改一行代码

        student2.setTeacher(new Teacher("汉口"));
false
student1:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student1:Student{number=null, teacher=Teacher{salary=null, address='武昌'}}
student2:Student{number=null, teacher=Teacher{salary=null, address='汉口'}}

可以发现student1的address没变
显而易见,浅克隆中属性如果是一个类的话,那么复制的是这个类的地址

2. 深克隆

  • 深克隆: 是在引用类型的类中也实现了clone,是clone的嵌套,复制后的对象与原对象之间完全不会影响。
  • 实现 : 不仅需要将被复制的类实现Clonenable接口,覆盖clone()方法而且该类中的某个类型为类的属性也需要被复制的话那这个类也需要实现Clonenable接口,覆盖clone()方法;
  • 如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。

3. 使用序列化的方式解决多层克隆

  • 使用序列化也能完成深复制的功能:对象序列化后写入流中,此时也就不存在引用什么的概念了,再从流中读取,生成新的对象,新对象和原对象之间也是完全互不影响的。

    public class Test {
    
      public static void main(String[] args) throws Exception {
          Teacher teacher = new Teacher();
          teacher.setAddress("西湖");
          Teacher teacher1 = (Teacher) cloneObj(teacher);
          System.out.println(teacher==teacher1);
          System.out.println("teacher:"+teacher);
          System.out.println("teacher1:"+teacher1);
      }
    
      public static Object cloneObj(Teacher teacher) throws Exception {
          ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
          ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
          objOut.writeObject(teacher);
    
          ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
          ObjectInputStream objIn = new ObjectInputStream(byteIn);
         return objIn.readObject();
      }
    }
    
    false
    teacher:Teacher{salary=null, address='西湖'}
    teacher1:Teacher{salary=null, address='西湖'}
    

文章作者: kangshifu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kangshifu !
 上一篇
接口和抽象类 接口和抽象类
抽象类我们都知道在面向对象的领域一切都是对象。同时,所有的对象都是通过类来描述的,但是并不是所有的类都是可以描述对象(对象 = 状态 + 行为)的。如果一个类没有足够的信息来描述一个具体的对象,那么我们就可以将这样的类设为抽象类。抽象类
2018-06-06
下一篇 
工厂模式 工厂模式
1. 简单工厂模式(SimpleFactory Mode)  简单工厂模式的思路是,首先我们把一些共性的东西(算法)拿出来,进行抽象,比如加减乘除。然后我们在定义一个类作为工厂类,工厂类的作用就是根据传过来的字符串或者其他Key值给返
2018-05-31
  目录