• 欢迎光临~

【当年笔记】克隆和序列化

开发技术 开发技术 2022-06-08 次浏览

1.浅克隆

需要克隆的对象必须实现 Cloneable 接口,并重写 clone() 方法,即可实现对此对象的克隆。 只会复制对象的值类型,而不会复制对象的引用类型。

2.深克隆

深克隆就是复制整个对象信息,包含值类型和引用类型。

2.1深克隆实现方式

  • 序列化实现深克隆:先将原对象序列化到内存的字节流中,再从字节流中反序列化出刚刚存储的对象,这个新对象和原对象就不存在任何地址上的共享,这样就实现了深克隆。
  • 所有引用类型都实现克隆:要复制对象的所有引用类型都要实现克隆,所有对象都是复制的新对象,从而实现了深克隆。
    深克隆实现方式一:序列化
    实现思路:先将要拷贝对象写入到内存中的字节流中,然后再从这个字节流中读出刚刚存储的信息,作为一个新对象返回,那么这个新对象和原对象就不存在任何地址上的共享,自然实现了深拷贝。 参考代码:
class CloneTest {
        public static void main(String[] args) throws CloneNotSupportedException {
            BirdChild birdChild = new BirdChild();
            birdChild.name = "小小鸟";
            Bird bird = new Bird();
            bird.name = "小鸟";
            bird.birdChild = birdChild;
            // 使用序列化克隆对象
            Bird bird2 = CloneUtils.clone(bird);
            bird2.name = "黄雀";
            bird2.birdChild.name = "小黄雀";
            System.out.println("bird name:" + bird.name);
            System.out.println("bird child name:" + bird.birdChild.name);
            System.out.println("bird name 2:" + bird2.name);
            System.out.println("bird child name 2:" + bird2.birdChild.name);
        }
    }
    class CloneUtils {
        public static <T extends Serializable> T clone(T 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;
        }
    }

深克隆实现方式二:所有引用类型都实现克隆

    class CloneableTest {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
        ParrotChild parrotChild = new ParrotChild();
            parrotChild.name = "小鹦鹉";
            Parrot parrot = new Parrot();
            parrot.name = "大鹦鹉";
            parrot.parrotChild = parrotChild;
            // 克隆
            Parrot parrot2 = (Parrot) parrot.clone();
            parrot2.name = "老鹦鹉";
            parrot2.parrotChild.name = "少鹦鹉";
            System.out.println("parrot name:" + parrot.name);
            System.out.println("parrot child name:" + parrot.parrotChild.name);
            System.out.println("parrot name 2:" + parrot2.name);
            System.out.println("parrot child name 2:" + parrot2.parrotChild.name);
        }
     }
    class Parrot implements Cloneable {
        public String name;
        public ParrotChild parrotChild;
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Parrot bird = (Parrot) super.clone();
            bird.parrotChild = (ParrotChild) parrotChild.clone();
            return bird;
        }
    }
    class ParrotChild implements Cloneable {
        public String name;
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

3.序列化和反序列化

将对象转换成二进制流的过程叫做序列化,把二进制流恢复为数据对象的过程就称之为反序列化

3.1序列化和反序列参考代码

先把对象序列化到磁盘,再从磁盘中反序列化出对象:


    class SerializableTest {
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            // 对象赋值
            User user = new User();
            user.setName("老王");
            user.setAge(30);
            System.out.println(user);
            // 创建输出流(序列化内容到磁盘)
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.out"));
            // 序列化对象
            oos.writeObject(user);
            oos.flush();
            oos.close();
            // 创建输入流(从磁盘反序列化)
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.out"));
            // 反序列化
            User user2 = (User) ois.readObject();
            ois.close();
            System.out.println(user2);
        }
    }
    class User implements Serializable {
        private static final long serialVersionUID = 3831264392873197003L;
        private String name;
        private int age;
        @Override
        public String toString() {
            return "{name:" + name + ",age:" + age + "}";
        }
        // setter/getter...
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }
程序员灯塔
转载请注明原文链接:【当年笔记】克隆和序列化
喜欢 (0)