序列化与反序列化

关于序列化的几个问题

  • 什么是序列化和反序列化
  • 为什么要序列化,如何序列化
  • serialVersionUID 这个的值有什么用,如何设置。

一、序列化和反序列化的概念
序列化:把对象转换为字节序列的过程。
反序列化:把字节序列恢复为对象的过程。

二、什么情况下需要序列化

  • 需要把内存中的对象状态保存到一个文件中或者数据库中时候;
  • 需要用套接字在网络上传送对象的时候;
  • 需要通过RMI传输对象的时候;(我也没用过=。=)

三、如何实现序列化
实现Serializable接口即可

先上对象代码,Student.java

public class Student implements Serializable {
    //  private static final long serialVersionUID = 1L;
    private static String age = "22";
    private String name;
    private String classNo;
    transient private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getClassNo() {
        return classNo;
    }

    public void setClassNo(String classNo) {
        this.classNo = classNo;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", classNo='" + classNo + '\'' +
                ", sex='" + sex + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

注释的代码,是一会儿要各种情况下使用的。

下面看main方法

package com.test;

import java.io.*;

public class SerializableTest {
    public static void main(String[] args) throws Exception {
        serializeStudent();
        Student stu = deserializeStudent();
        System.out.println(stu.toString());
    }

    /**
     * 序列化
     */
    private static void serializeStudent() throws Exception {
        Student stu = new Student();
        stu.setName("yang");
        stu.setClassNo("c221");
        stu.setSex("女");
        // ObjectOutputStream 对象输出流,将 stu 对象存储到E盘的 stu.txt 文件中,完成对 stu 对象的序列化操作
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:/stu.txt")));
        oos.writeObject(stu);
        System.out.println("stu 对象序列化成功!");
        oos.close();
    }

    /**
     * 反序列化
     */
    private static Student deserializeStudent() throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("d:/stu.txt")));
        Student stu = (Student) ois.readObject();
        System.out.println("Student 对象反序列化成功!");
        return stu;
    }

}

对上面的2个操作文件流的类的简单说明

ObjectOutputStream代表对象输出流:

writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

ObjectInputStream代表对象输入流:

readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

下面运行情况。

先直接run。

实际运行结果,他会在 d:/stu.txt 生成个文件。

Student  对象序列化成功!
Student  对象反序列化成功!
Student {name='yang', classNo='c221', sex='null', age='22'}

从运行结果上看:

  • 实现了对象的序列化和反序列化。
  • transient 修饰的属性,是不会被序列化的。设置的sex是null。

进一步验证静态的属性能不能被序列化和反序列化。

1、将带静态变量的对象序列化(age = 22)

public class SerializableTest {
    public static void main(String[] args) throws Exception {
        serializeStudent();
//      Student stu = deserializeStudent();
//      System.out.println(stu.toString());
    }
}

2、修改该静态变量的值,把age改成26

3、执行反序列化

public class SerializableTest {
    public static void main(String[] args) throws Exception {
//      serializeStudent ();
        Student stu = deserializeStudent ();
        System.out.println(stu.toString());
    }
}

输出结果:

Student 对象反序列化成功!

Student {name='yang', classNo='c221', sex='null', age='26'}

4、分析:age=26,并没有达到预期拿到反序列化后的值22。由此静态static的属性,未序列化。

四、serialVersionUID 的作用和用法

代码比较重复这里就不贴了,直接描述操作。

1、不加serialVersionUID ,执行序列化方法。生成文件。
2、为对象添加属性classmateTotal后,再次执行反序列化方法。

抛异常:InvalidClassException 。大致就是说序列号不一致。

InvalidClassException: com.sample.Student; 
local class incompatible: 
stream classdesc serialVersionUID = -5633475314544497569, 
local class serialVersionUID = 74238907341209765348
  • serialVersionUID是序列化前后的唯一标识符
  • 如果没有人为显式定义过serialVersionUID,那编译器会为它自动声明一个.

再验证一下

1、添加serialVersionUID ,执行序列化方法。生成文件。
2、为对象添加属性classmateTotal = “66”后,再次执行反序列化方法。

Student 对象反序列化成功!
Student {name='yang', classNo='c221', sex='null', age='26',classmateTotal='66'}

总上:serialVersionUID是序列化前后的唯一标识符。在反序列化时,JVM会把字节流中的序列号ID和被序列化类中的序列号ID做比对,两者一致,才能重新反序列化,否则就会报异常来终止反序列化的过程。

如何添加serialVersionUID呢?

1、可以Java自动帮你赋值,但是后期类拓展时会有上述异常。

2、手动添加如:private static final long serialVersionUID = 1L;。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值