zoukankan      html  css  js  c++  java
  • 高质量编码--使用序列化实现对象的拷贝

    回顾

    回顾下对象拷贝的知识,为什么要拷贝对象呢,因为new对象往往是消耗资源的,使用对象拷贝的方式可以节省创建对象时的资源消耗,尤其对于大对象而言

    我们可以看下简单实现,下面这个类实现了Cloneable接口

    public class Person implements Cloneable{
            private String name;
            private Person parent;
    
            Person(String name){
                this.name = name;
            }
    
            Person(String name,Person parent){
                this.name = name;
                this.parent = parent;
            }
    
            @Override
            protected Object clone() throws CloneNotSupportedException {
                return super.clone();
            }
    
            // get,set方法省略...
    }
    

    类有了,下面这个方法会输出什么呢?

    public class Main {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Person father = new Person("老爹");
            Person xiaoming = new Person("小明", father);
            Person xiaogang = xiaoming.clone();
            xiaogang.name = "小刚";
            xiaoming.parent.name = "干爹";
            System.out.printf("%s的父亲-%s
    ",xiaoming.name,xiaoming.parent.name);
            System.out.printf("%s的父亲-%s
    ",xiaogang.name,xiaogang.parent.name);
        }
    

    Look

    我们现在假设个场景,小明和小刚是兄弟,他们俩的老爹欠了隔壁王大爷5块钱,木钱还咋办,老王说你让一个儿子认我做干爹,这事算结了,老爹没办法啊,只好同意了,于是小明认了老王做干爹,小刚看见了也去认老王当干爹去了,得,两个儿子全没了,老爹要气死

    这里就涉及到了浅拷贝的知识

    浅拷贝

    调用clone方法只会复制对象的基本类型和String,而对象则是复制引用,即小明和小刚的引用都是指向同一个父亲。
    有没有办法给小刚复制一个父亲,这样小明修改父亲属性就不会影响到小刚了。

    重写clone方法

    其实是有办法的,代码如下,给小刚重新new一个父亲就行。

    protected Person clone() throws CloneNotSupportedException {
        Person person = super.clone();
        person.setPerson(new Person(person.getName));
        return person;
    }
    

    序列化

    我们考虑这样一个问题,每次对象复制都要重写clone对象是不是很费事
    因此我们想到了其他方法,我们可以通过序列化的方式来处理,在内存中通过字节流的拷贝来实现。
    也就是把小明写到一个字节流中,再从字节流中读出来,这样就可以重建一个新对象了,这个对象跟小明不存在引用共享的问题,相当于深拷贝一个对象。

    代码如下

    class CloneUtils{
        // 拷贝一个对象
        public static <T extends Serializable> T clone(T obj){
            // 拷贝产生的对象
            T clonedObj = null;
            try {
                // 读取对象字节数据
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(obj);
                oos.close();
                // 分配内存空间,写入原始对象,生成新对象
                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bais);
                // 返回新对象,进行类型转换
                clonedObj = (T) ois.readObject();
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return clonedObj;
        }
    }
    

    当然,传入的类要实现Serializable.

    今天的文章结束了~
    Best Wish to you

  • 相关阅读:
    Android 编程下 Eclipse 恢复被删除的文件
    Android 编程下背景图片适配工具类
    Android 编程下 Managing Your App's Memory
    Android 编程下代码之(QQ消息列表滑动删除)
    Android 编程下 Canvas and Drawables
    Android 编程下 AlarmManager
    Android 编程下去除 ListView 上下边界蓝色或黄色阴影
    Java 编程下字符串的 16 位、32位 MD5 加密
    C#枚举类型和int类型相互转换
    MVC和普通三层架构的区别
  • 原文地址:https://www.cnblogs.com/lwhblog/p/12588391.html
Copyright © 2011-2022 走看看