目录
实现 Serializable 接口
serialVersionUID 版本号
IDEA 快捷键生成 serialVersionUID
序列化:即提取数据对象并将其转换为字节流(二进制格式)的过程,因此它可以通过网络传输或保存在数据库、以及本地文件中,后续可以再反序列化为对象。
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
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等等都是无效的。
1、打开 IDEA setting 窗口后直接搜索 "serialVersionUID",然后将 serializable class without ‘serialVersionUID’ 勾选上
2、需要生成 serialVersionUID 的类先实现 Serializable 接口
3、最后鼠标点击需要生成的类名,按下快捷键 alt+entry,即可选择进行生成。