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

  • 相关阅读:
    iaas,paas,saas理解
    July 06th. 2018, Week 27th. Friday
    July 05th. 2018, Week 27th. Thursday
    July 04th. 2018, Week 27th. Wednesday
    July 03rd. 2018, Week 27th. Tuesday
    July 02nd. 2018, Week 27th. Monday
    July 01st. 2018, Week 27th. Sunday
    June 30th. 2018, Week 26th. Saturday
    June 29th. 2018, Week 26th. Friday
    June 28th. 2018, Week 26th. Thursday
  • 原文地址:https://www.cnblogs.com/Yintianhao/p/10398455.html
Copyright © 2011-2022 走看看