• 47、序列化和反序列化


    在工作中有可能遇到多台机器远程通信的情况,如果要将机器A中的某个java对象传输到机器B上面,需要将这个java对象转换为字节序列然后进行传输。将对象转换为字节序列的过程叫做序列化,反之叫做反序列化。

    一个对象如果支持序列化,需要实现Serializable的接口,这个接口中没有任何方法,实现该接口后,JVM会给这个对象做特殊待遇

    将java对象保存到硬盘里面

    使用序列化还可以将一个对象保存到硬盘中,然后再通过反序列化将该对象读取到内存里面。

    创建一个Student类,实现Serializable接口

    package com.monkey1024.serializable;
    
    import java.io.Serializable;
    
    public class Student implements Serializable {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    使用ObjectOutputStream将Student对象写出到硬盘中

    package com.monkey1024.serializable;
    
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    
    /**
     * 将Student对象序列化到硬盘中
     *
     */
    public class ObjectOutput {
    
        public static void main(String[] args) {
            Student s = new Student();
            s.setName("张三");
    
            // 创建输出流(序列化流) 
            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("zhangsan"));) {
                //将对象写出到硬盘中
                oos.writeObject(s);
                oos.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    使用ObjectInputStream将硬盘中的对象读取到内存中

    package com.monkey1024.serializable;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    
    /**
     * 从硬盘中读取Student对象
     *
     */
    public class ObjectInput {
    
        public static void main(String[] args) {
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("zhangsan"));) {
                Student s = (Student)ois.readObject();
                System.out.println(s.getName());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    序列化版本号

    在一个类实现Serializable接口后,系统会给每个对象一个序列化版本号,当这个类的源码被修改后,系统会重新分配一个新的序列化版本号,这样做的好处就是保证序列化和反序列化的对象内容一致。例如将一个对象序列化到硬盘之后,修改这个对象所对应类的源码,在进行反序列化是就会报出InvalidClassException异常。如果手动编写序列化版本号之后,就不会出现这个异常了。

    package com.monkey1024.serializable;
    
    import java.io.Serializable;
    
    public class Student implements Serializable {
    
        /**
         * 自动生成序列化版本号
         */
        private static final long serialVersionUID = -716323668524282676L;
    
        private String name;
        private int age;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    transient关键字

    如果不希望将Student类中的age属性序列化,可以使用transient声明该属性,在序列化时将忽略这个属性。

    package com.monkey1024.serializable;
    
    import java.io.Serializable;
    
    public class Student implements Serializable {
    
        /**
         * 自动生成序列化版本号
         */
        private static final long serialVersionUID = -716323668524282676L;
    
        private String name;
    
        //age不序列化
        transient private int age;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
  • 相关阅读:
    使用kindeditor获取不到富文本框中的值
    ASP.NET中的文件操作(文件信息,新建,移动,复制,重命名,上传,遍历)
    2018 遇到selenium.common.exceptions.WebDriverException问题
    DataTable与实体类互相转换
    反射load,loadfile,LoadFrom区别
    DbSet.Attach(实体)与DbContext.Entry(实体).State = EntityState.Modified 区别
    .net 面试总结
    C# Linq 常用查询操作符
    windows下nginx的安装及使用
    熊猫热土-环汶川50公里越野赛赛记
  • 原文地址:https://www.cnblogs.com/zhuifeng-mayi/p/10145545.html
Copyright © 2020-2023  润新知