Java序列化与反序列化

1、什么是序列化与反序列化?

Java 序列化是指把 Java 对象转换为字节序列的过程;
Java 反序列化是指把字节序列恢复为 Java 对象的过程;java

2、为何要用序列化与反序列化?

为何要用序列化与反序列化 以前咱们先了解一下对象序列化的两种用途:api

  1. 把对象的字节序列永久地保存到硬盘上,一般存放在一个文件中;
  2. 在网络上传送对象的字节序列。

咱们能够想一想若是没有序列化以前,又是怎样一种情景呢?服务器

举例:
Web 服务器中的 Session 会话对象,当有10万用户并发访问,就有可能出现10万个 Session 对象,显然这种状况内存多是吃不消的。微信

因而 Web 容器就会把一些 Session 先序列化,让他们离开内存空间,序列化到硬盘中,当须要调用时,再把保存在硬盘中的对象还原到内存中。网络


咱们知道,当两个进程进行远程通讯时,彼此能够发送各类类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。并发

一样的序列化与反序列化则实现了 进程通讯间的对象传送,发送方须要把这个Java对象转换为字节序列,才能在网络上传送;接收方则须要把字节序列再恢复为Java对象。app

初步总结:Java 序列化和反序列化,其一,实现了数据的持久化,经过序列化能够把数据永久的保存在硬盘上;其二,利用序列化实现远程通讯,即在网络上传递对象的字节序列。工具

3、如何实现序列化与反序列化?

3.1 JDK 类库中序列化 API

使用到JDK中关键类 ObjectOutputStream(对象输出流) 和ObjectInputStream(对象输入流)测试

ObjectOutputStream 类中:经过使用 writeObject(Object object) 方法,将对象以二进制格式进行写入。this

ObjectInputStream 类中:经过使用 readObject()方法,从输入流中读取二进制流,转换成对象。

3.2 目标对象实现 Serializable 接口

咱们建立一个 User 类,实现 Serializable 接口,并生成一个版本号 :

public class User implements Serializable {

    private static final long serialVersionUID = 3604972003323896788L;
    private transient int age;
    private String name;
    private String sex;

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

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

首先:

一、Serializable 接口的做用只是用来标识咱们这个类是须要进行序列化,而且 Serializable 接口中并无提供任何方法。

二、SerialVersionUid 序列化版本号的做用是用来区分咱们所编写的类的版本,用于判断反序列化时类的版本是否一直,若是不一致会出现版本不一致异常。

三、transient 关键字,主要用来忽略咱们不但愿进行序列化的变量

因为第一种形式太不常见,顾再也不啰嗦演示,直接来看第二种实现 Serializable 接口的写入方式:

定义一个Person类,实现Serializable接口

public class Person implements Serializable {

    private static final long serialVersionUID = -5809452578272945389L;
    private int age;
    private String name;
    private String sex;

    get..

    set...
}

序列化和反序列化Person类对象

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;

/**
 * <p>Description: 测试对象的序列化和反序列<p>
 */

public class TestObjSerializeAndDeserialize {

    public static void main(String[] args) throws Exception {
        SerializePerson();//序列化Person对象
        Person p = DeserializePerson();//反序列Perons对象
        System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
                                                 p.getName(), p.getAge(), p.getSex()));
    }

    /**
     * Description: 序列化Person对象
     */

    private static void SerializePerson() throws FileNotFoundException,
            IOException 
{
        Person person = new Person();
        person.setName("gacl");
        person.setAge(25);
        person.setSex("男");
        // ObjectOutputStream 对象输出流,将Person对象存储到E盘的Person.txt文件中,完成对Person对象的序列化操做
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
                new File("E:/Person.txt")));
        oo.writeObject(person);
        System.out.println("Person对象序列化成功!");
        oo.close();
    }

    /**
     * Description: 反序列Perons对象
     */

    private static Person DeserializePerson() throws Exception, IOException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                new File("E:/Person.txt")));
        Person person = (Person) ois.readObject();
        System.out.println("Person对象反序列化成功!");
        return person;
    }

}

代码运行结果:

疑问:Person 实体中的 serialVersionUID 是个什么鬼?

答:序列化版本号,取值是 Java 运行时环境根据类的内部细节自动生成的。若是对类的源代码做了修改,再从新编译,新生成的类文件的 serialVersionUID 的取值有可能也会发生变化。。

既然程序帮我门自动生成,那为什么还要去定义该属性?

序列化和反序列化就是经过对比其 SerialversionUID 来进行的,咱们修改一个实现 Serializable 接口的实体类,从新编译后,显然程序会从新会生成新值,那么一旦SerialversionUID 跟以前不匹配,反序列化就没法成功。

在实际的生产环境中,咱们可能会建一系列的中间 Object 来反序列化咱们的 pojo,为了解决这个问题,咱们就须要在实体类中自定义 SerialversionUID,就像上方示例,无论咱们序列化以后如何更改咱们的 实体(不删除原有字段),最终均可以反序列化成功。。

4、总结

什么是序列化,如何实现序列化?

Java 中对象的序列化就是将对象转换成二进制序列,反序列化则是将二进制序列转换成对象。
采用Java序列化与反序列化技术:

  • 一是能够实现数据的持久化,在MVC模式中非常有用;
  • 二是能够对象数据的远程通讯。

Java 实现序列化的多种方式

  1. 首先须要使用到工具类 ObjectInputStream 和ObjectOutputStream 两个IO类
  2. 实现 Serializable 接口
  3. 实现 Externalizable 接口

若是文章有错的地方欢迎指正,你们互相留言交流。习惯在微信看技术文章,想要获取更多的Java资源的同窗,能够关注微信公众号:niceyoo

相关文章
相关标签/搜索