不积跬步,无以至千里;不积小流,无以成江海。

 

Java语言基础

 

一、基本概念

1. 序列化与反序列化

序列化指的是对象的序列化,流化,是将对象转换为容易传输的格式的过程

反序列化将从该流重新构造对象。也是对象持久化的一种机制

作用

序列化:在传递和保存对象时.保证对象的完整性和可传递性。以便在网络上传输或者保存在本地文件中。

反序列化:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。

总结:核心作用就是对象状态的保存和重建。 

2. json/xml的数据传递

在数据传输(也可称为网络传输)前,先通过序列化工具类将Java对象序列化为json/xml文件。

在数据传输(也可称为网络传输)后,再将json/xml文件反序列化为对应语言的对象

3. 序列化算法

将对象实例相关的类元数据输出。

递归地输出类的超类描述直到不再有超类。

类元数据输出完毕后,从最顶端的超类开始输出对象实例的实际数据值。

从上至下递归输出实例的数据。

4. 用途举例

应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中

 

二、Java实现序列化和反序列化的过程

1. 实现序列化的必备要求

只有实现了Serializable或者Externalizable接口的类的对象才能被序列化为字节序列。(不是则会抛出异常)

Externalizable接口继承自 Serializable接口

2. JDK中序列化和反序列化的API

 java.io.ObjectInputStream

对象输入流,readObject()方法从输入流中读取字节序列,然后将字节序列反序列化为一个对象并返回。

java.io.ObjectOutputStream

对象输出流,writeObject(Object obj)方法将将传入的obj对象进行序列化,把得到的字节序列写入到目标输出流中进行输出。

3. 对象序列化和反序列化步骤:

3.1 序列化步骤

创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;

通过对象输出流的writeObject()方法写对象。

3.2 对象反序列化的步骤如下:

创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

通过对象输入流的readObject()方法读取对象。 

 

4. 示例

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

import java.io.Serializable;

public class Person implements Serializable {

    /**序列化ID*/
    private static final long serialVersionUID = -5809782578272943999L;
    private 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;
    }
}

序列化反序列化Person对象

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()));
    }

    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();
    }

    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;
    }

}

4.1 序列化图示

 

4.2 反序列化图示 

 

三、序列化和反序列化的注意点

3.1 序列化时,只对对象的状态进行保存,而不管对象的方法;

3.2 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

3.3 声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。

3.4 Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是也有一些没有实现serializable接口的;

 

四、serialVersionUID的作用

s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D​:​ ​字​面​意​思​上​是​序​列​化​的​版​本​号​,凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量

private static final long serialVersionUID

实现Serializable接口的类如果类中没有添加serialVersionUID,那么就会出现如下的警告提示

serialVersionUID有两种生成方式:

  采用这种方式生成的serialVersionUID是1L,例如:

private static final long serialVersionUID = 1L;

  采用这种方式生成的serialVersionUID是根据类名,接口名,方法和属性等来生成的,例如:

private static final long serialVersionUID = 4603642343377807741L;

举例说明serialVersionUID的作用 

public class TestSerialversionUID {

    public static void main(String[] args) throws Exception {
        SerializeCustomer();// 序列化Customer对象
        Customer customer = DeserializeCustomer();// 反序列Customer对象
        System.out.println(customer);
    }

    private static void SerializeCustomer() throws FileNotFoundException,
            IOException {
        Customer customer = new Customer("gacl",25);
        // ObjectOutputStream 对象输出流
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
                new File("E:/Customer.txt")));
        oo.writeObject(customer);
        System.out.println("Customer对象序列化成功!");
        oo.close();
    }

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

class Customer implements Serializable {
    //Customer类中没有定义serialVersionUID
    private String name;
    private int age;

    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "name=" + name + ", age=" + age;
    }
}

  运行结果:

序列化和反序列化都成功了。

当修改一下Customer类,添加多一个sex属性,如下:

class Customer implements Serializable {
    //Customer类中没有定义serialVersionUID
    private String name;
    private int age;

    //新添加的sex属性
    private String sex;

    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Customer(String name, int age,String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "name=" + name + ", age=" + age;
    }
}

  抛出如下的异常信息:

Exception in thread "main" java.io.InvalidClassException: Customer; 
local class incompatible: 
stream classdesc serialVersionUID = -88175599799432325, 
local class serialVersionUID = -5182532647273106745 

修改过后的class,不兼容了,处于安全机制考虑,程序抛出了错误,并且拒绝载入。  

 

借鉴博客: https://www.cnblogs.com/xdp-gacl/p/3777987.html

              https://blog.csdn.net/tree_ifconfig/article/details/82766587

posted on 2021-05-29 10:26  smile学子  阅读(112)  评论(0编辑  收藏  举报