zoukankan      html  css  js  c++  java
  • Java序列化和反序列化

    什么叫序列化和反序列化?

    序列化:对象转化为字节序列的过程叫做对象的序列化

    反序列化:字节序列恢复为对象的过程叫做对象的反序列化

    为啥要序列化?(序列化的用途)

    -需要将对象永久的保存在硬盘中(比如Session对象)

    -网络传输对象的序列(网络中的二进制序列)

    过程:

    序列化的过程:创建一个对象输出流对象,调用对象的writeObject()函数

    反序列化的过程,创建一个对象输入流,调用readObject()函数

    例子:

    package Note;
    
    import java.io.*;
    
    /**
     * @author yintianhao
     * @createTime 20190218 21:46
     * @description 序列化
     */
    public class People implements Serializable {
        //序列化id
        private static final long serialVersionUID = -5809782578272943999L;
    
        private int age;
        private String name;
    
    
        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;
        }
    
        public static void main(String[] args) throws IOException,ClassNotFoundException {
            //序列化
            People one = new People();
            one.setAge(5);
            one.setName("张三");
            ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(new File("G:/test.txt")));
            stream.writeObject(one);
            stream.close();
    
            //反序列化
            ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt")));
            People two = (People) stream1.readObject();
            System.out.println("Name = "+two.getName()+"--age = "+two.getAge());
            stream1.close();
        }
    }
    Code

    检验一下G盘是否有这个test.txt

     再看Console

    那么问题来了:serialVersionUID是干啥的? 

    看字面上的意思就是版本号嘛,那么这个版本号是干啥的呢

    那么就有必要了解一下序列化的过程了:

    序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。

    当然这里是我自己指定的serialVersionUID,如果这里我们不写也是没问题的,因为如果我们自己没定义serialVersionUID

    jdk会自行给我们生成一个serialVersionUID,但是一般情况IDE会报个警告,不知道为啥IDEA没报,但是Eclipse是报了...

    第一句是生成默认的版本ID,值为

    第二句是根据类的类名信息等生成的,值为

    但是如果我们不指定ID,那么,如果我们修改了类中的信息,比如增加或者删除某个属性,那么我们在反序列化之前的

    对象的时候就会报错,因为这个修改后的类的serialVersionUID已经变了,所以不能反序列化第一次的对象

    打个比方增加一个性别sex的选项,然后为了验证把之前的序列化的过程去掉,看改完后的这个能不能反序列化之前的

    代码如下:

    package Note;
    
    import java.io.*;
    
    /**
     * @author yintianhao
     * @createTime 20190218 21:46
     * @description 序列化
     */
    public class People implements Serializable {
        //序列化id
    
        private int age;
        private String name;
        private String sex;
    
        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;
        }
    
        public static void main(String[] args) throws IOException,ClassNotFoundException {
           
    
            //反序列化
            ObjectInputStream stream1 = new ObjectInputStream(new FileInputStream(new File("G:/test.txt")));
            People two = (People) stream1.readObject();
            System.out.println("Name = "+two.getName()+"--age = "+two.getAge());
            stream1.close();
        }
    }
    Code

    运行,就报错了

    Exception in thread "main" java.io.InvalidClassException: Note.People; local class incompatible: stream classdesc serialVersionUID = 8716394284034362776, local class serialVersionUID = 5389077117487999490
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    at Note.People.main(People.java:37)

    这里这个ID是由JDK的生成的,根据类的一些细节信息生成,具体怎么生成的我们不管,但是像刚才那样我们是不愿看见的,因为不同的Java编译器可能生成的

    ID就不一样,所以还是强烈建议自定义一个明确的serialVersionUID

    参考博客:https://www.cnblogs.com/xdp-gacl/p/3777987.html

    https://www.cnblogs.com/duanxz/p/3511695.html

  • 相关阅读:
    Python网络编程(weekly summary1)
    Python网络编程(子进程的创建与处理、简单群聊工具)
    Python网络编程(epoll内核监听,多任务多进程)
    Python网络编程(http协议,IO多路复用、select内核监听)
    Python网络编程(socket模块、缓冲区、http协议)
    Python网络编程(OSI模型、网络协议、TCP)
    Linux(Ubuntu 命令大全)
    计算机中的进制和编码
    算法图解(选择排序)
    Python全栈 MySQL 数据库(SQL命令大全、MySQL 、Python调用)
  • 原文地址:https://www.cnblogs.com/Yintianhao/p/10398455.html
Copyright © 2011-2022 走看看