zoukankan      html  css  js  c++  java
  • 对象的克隆

    对象的克隆

    1、克隆即复制的意思,对象的克隆,意味着生成一个对象,这个对象和某个对象的属性和行为是一致的,但是这个对象和源对象是两个不同的对象。实现对象的克隆,方法是实现Cloneable接口,否则会报异常CloneNotSupportedException

     1 public class Demo implements Cloneable{
     2     private int number;
     3     private String name;
     4     
     5     public int getNumber() {
     6         return number;
     7     }
     8     public void setNumber(int number) {
     9         this.number = number;
    10     }
    11     public String getName() {
    12         return name;
    13     }
    14     public void setName(String name) {
    15         this.name = name;
    16     }
    17 
    18 
    19     public static void main(String[] args) {
    20         Demo demo = new Demo();
    21         Demo demo2 = null;
    22         try {
    23             demo2 = (Demo) demo.clone();
    24             System.out.println(demo==demo2);
    25             
    26         } catch (CloneNotSupportedException e) {
    27             e.printStackTrace();
    28         }
    29     }
    30 }

    输出:

    false

    从结果我们可以知道,两个引用指向的对象是两个不同的Demo对象.

    2、浅克隆

    浅克隆是指在克隆对象的时候,对于对象中的属性的值进行复制,那么这里引出一个问题,如对象的成员变量不论是基本类型还是引用类型,克隆对象的成员变量的值与源对象一致,这里引出一个问题,当成员变量是引用类型的时候,克隆对象和源对象的引用成员类型变量指向的是同一个对象,那么当这个对象本身的内容发生改动的时候,势必影响到克隆对象和源对象,这样在实际的生产过程可能带来巨大问题。因此对象的克隆只在特定的场景下使用。

    浅克隆的例子:

     1 public class Demo implements Cloneable{
     2     private int number;
     3     private Person person;
     4     public int getNumber() {
     5         return number;
     6     }
     7     public void setNumber(int number) {
     8         this.number = number;
     9     }
    10     public Person getPerson() {
    11         return person;
    12     }
    13     public void setPerson(Person person) {
    14         this.person = person;
    15     }
    16     
    17     public static void main(String[] args) {
    18         Demo demo = new Demo();
    19         demo.setNumber(10);
    20         Person person = new Person();
    21         person.setName("test");
    22         demo.setPerson(person);
    23         Demo demo2 = null;
    24         try {
    25             demo2 = (Demo) demo.clone();
    26             //很明显,源对象和克隆对象的引用类型变量指向同一个Person对象
    27             System.out.println(demo.getPerson()==demo2.getPerson());
    28             System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName());
    29             //person对象发生变动
    30             person.setName("demo");
    31             System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName());
    32             
    33         } catch (CloneNotSupportedException e) {
    34             e.printStackTrace();
    35         }
    36     }
    37 }
    38 
    39 class Person{
    40     private String name;
    41 
    42     public String getName() {
    43         return name;
    44     }
    45     public void setName(String name) {
    46         this.name = name;
    47     }
    48 }

    输出结果:

    true
    test:test
    demo:demo

    3、深克隆

    在克隆时引用类型的变量在源对象和克隆对象中指向同一个对象。那么能否做到克隆出来的对象的引用属性指向的对象与源对象是两个不同的对象呢?答案是可以的,这种克隆被称为深克隆。与浅克隆区别在于,复制对象的时候,是否对源对象中的引用变量指向的对象进行拷贝。进行深克隆的常用的手段是通过流和序列化/反序列化来实现。

     1 public class Demo implements Serializable{
     2     private int number;
     3     private Person person;
     4     public int getNumber() {
     5         return number;
     6     }
     7     public void setNumber(int number) {
     8         this.number = number;
     9     }
    10     public Person getPerson() {
    11         return person;
    12     }
    13     public void setPerson(Person person) {
    14         this.person = person;
    15     }
    16     
    17     public static void main(String[] args){
    18         Demo demo = new Demo();
    19         demo.setNumber(10);
    20         Person person = new Person();
    21         person.setName("test");
    22         demo.setPerson(person);
    23         Demo demo2 = ObjectUtil.clone(demo);
    24         System.out.println(demo.getPerson()==demo2.getPerson());
    25         System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName());
    26         //person对象发生变动
    27         person.setName("demo");
    28         System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName());
    29     }
    30 }
    31 
    32 class Person implements Serializable{
    33     private String name;
    34 
    35     public String getName() {
    36         return name;
    37     }
    38     public void setName(String name) {
    39         this.name = name;
    40     }
    41 }

    工具类:

     1 public class ObjectUtil {
     2     @SuppressWarnings("unchecked")
     3     public static <T>T clone(T obj){
     4         T clonedObj = null;
     5         try {
     6             ByteArrayOutputStream baos = new ByteArrayOutputStream();
     7             //将对象写进字节流中
     8             ObjectOutputStream oos = new ObjectOutputStream(baos);
     9             oos.writeObject(obj);
    10             //从字节流中读出对象
    11             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    12             ObjectInputStream ois = new ObjectInputStream(bais);
    13             clonedObj = (T)ois.readObject();
    14         }catch (IOException e) {
    15             e.printStackTrace();
    16         }catch (ClassNotFoundException e) {
    17             e.printStackTrace();
    18         }
    19         return clonedObj;
    20     }
    21 }
  • 相关阅读:
    pyhon3 mysql的下载和配置
    python3 进程池和线程池
    python3 udp socketserver
    python3 多进程实现socket通讯
    python3 在一个进程内开启多个线程实现socket通讯
    python3 单线程(gevent)实现并发的socket通讯
    python3 协程gevent模块(遇到IO自动切换)
    python3 greenlet模块
    python3 协程函数yeild
    python3 线程队列queue
  • 原文地址:https://www.cnblogs.com/liupiao/p/9254601.html
Copyright © 2011-2022 走看看