Java Serializable 序列化 与 serialVersionUID 版本号

目录

实现 Serializable 接口

serialVersionUID 版本号

IDEA 快捷键生成 serialVersionUID


序列化:即提取数据对象并将其转换为字节流(二进制格式)的过程,因此它可以通过网络传输或保存在数据库、以及本地文件中,后续可以再反序列化为对象。

实现 Serializable 接口

1、使用默认的序列化机制,即实现 Serializable 接口即可,不需要实现任何方法。

2、Serializable 接口没有任何方法,只是一个标记而已,告诉Java虚拟机该类可以被序列化了。利用 ObjectOutputStream 的writeObject(object) 方法进行序列化,用 ObjectInputStream 的 readObject() 方法进行反序列化。

3、该方式下序列化机制会自动保存该对象的成员变量,static 成员变量和 transient 关键字修饰的成员变量不会被序列化保存

准备 User 实体类如下:

import java.io.Serializable;
import java.util.Date;
/**
 * Created by Administrator on 2018/7/31 0031.
 * 用户类----实现 Serializable 接口
 */
public class User implements Serializable {
    private static final long serialVersionUID = 1749243243491717954L;//具体数值自己定义
    private Integer id;
    private String name;
    private Date birthday;
    private static String address = "China";//默认情况下,静态属性不会被序列化

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public static String getAddress() {
        return address;
    }

    public static void setAddress(String address) {
        User.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

序列化如下:

import java.io.*;
import java.util.Date;
/**
 * Created by Administrator on 2018/7/25 0025.
 */
public class Test {
    public static void main(String[] args) {
        User user = new User();
        user.setId(9527);
        user.setName("华安");
        user.setBirthday(new Date());
        User.setAddress("USA");

        String path = "D:/abc.txt";//序列化保存在本地的位置
        new Test().serialize(user, path);
    }

    /**
     * 将对象序列化到指定文件
     *
     * @param user
     * @param path
     */
    public void serialize(User user, String path) {
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(new File(path));
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(user);
            objectOutputStream.flush();
            objectOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

代码运行后,就会在 D:/abc.txt 文件中保存好序列化后的数据。

反序列化:

import java.io.*;
/**
 * Created by Administrator on 2018/7/25 0025.
 */
public class Test {
    public static void main(String[] args) {
        String path = "D:/abc.txt";//序列化保存在本地的位置
        new Test().deserialize(path);
    }
    /**
     * 从文件反序列化
     *
     * @param path
     */
    public void deserialize(String path) {
        try {
            FileInputStream fileInputStream = new FileInputStream(new File(path));
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            Object user = objectInputStream.readObject();
            objectInputStream.close();
            System.out.println("反序列化结果 user :" + user);
            System.out.println("反序列化结果 User.getAddress():" + User.getAddress());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

控制台输出如下:

反序列化结果 user :User{id=9527, name='华安', birthday=Wed Jul 10 14:46:09 CST 2019}
反序列化结果 User.getAddress():China

serialVersionUID 版本号

1、序列化后,如上 User 所示,其中通常都会一行代码:private static final long serialVersionUID = 1749243243491717954L;

2、假设类 A 实现 Serializable 接口,当使用序列化将对象传输到了其它地方,此时因为一些原因修改了类 A(比如添加属性、删除属性、修改属性等),那么之前序列化后的数据能否再反序列化为对象呢?

1)如果类中自定义了 serialVersionUID 属性,且值未发生变化,则可以正确反序列化回来。

2)如果类中没有自定义 serialVersionUID 属性,则此时无法反序列化为对象,并报错如下:

java.io.InvalidClassException: wmx.com.springboothello.test.User; local class incompatible: stream classdesc serialVersionUID = -4467989014877592694, local class serialVersionUID = -7572413328418759383

3、假设类 B 实现 Serializable 接口,类中没有自定义 serialVersionUID 属性,则序列化时会根据算法得到一个默认值,之后只要类 B 没有做修改,则这个默认的 serialVersionUID 值会一直不变,反序列化也就不会有问题。如果之后类 B 发生了变化,则此时它的 serialVersionUID 也会发生变化,旧的 serialVersionUID 值反序列化时就会因为值不匹配新值而发生如上错误。

4、同理假如类 C 实现 Serializable 接口,类中自定义了 serialVersionUID 属性值,后面如果修改了类 C ,但只要 serialVersionUID 属性值不变,则之前序列化的内容仍然可以正常反序列化。如果此时不想再让以前序列化的内容能反序列化成功,则只需要手动修改 serialVersionUID 属性值即可。

5、serialVersionUID 属性值可以自己随意指定,但是名称必须写死,如果写成 suid、seriaUID等等都是无效的。

IDEA 快捷键生成 serialVersionUID

1、打开 IDEA setting 窗口后直接搜索 "serialVersionUID",然后将 serializable class without ‘serialVersionUID’ 勾选上

2、需要生成 serialVersionUID  的类先实现 Serializable 接口

3、最后鼠标点击需要生成的类名,按下快捷键 alt+entry,即可选择进行生成。

Java Serializable 序列化 与 serialVersionUID 版本号_第1张图片

 

你可能感兴趣的:(Java_SE)