1. 序列化和反序列化的意思
序列化:将对象转化为字节序列的过程,这些字节序中包含了对象的字段和方法。序列化后的对象可以被写到数据库、写到文件,也可用于网络传输。
反序列化:将字节序列转化成对象的过程
2. 为什么要去进行序列化?
- 持久化:对象是存储在
JVM
中的堆区的,但是如果JVM
停止运行了,对象也不存在了。序列化可以将对象转化成字节序列,可以写进硬盘文件中实现持久化。在新开启的JVM
中可以读取字节序列进行反序列化成对象。 - 网络传输:网络直接传输数据,但是无法直接传输对象,可在传输前序列化,传输完成后反序列化成对象。所以所有可在网络上传输的对象都必须是可序列化的。
3. 怎么实现对象的序列化和反序列化?
Java为我们提供了对象序列化的机制,规定了要实现序列化对象的类要满足的条件和实现方法。
- 对于要序列化对象的类要去实现
Serializable
接口或者Externalizable
接口 - 实现方法:JDK提供的
ObjectOutputStream
和ObjectInputStream
来实现序列化和反序列化
3.1 实现Serializable
接口
public class TestBean implements Serializable {
private Integer id;
private String name;
private Date date;
//省去getter和setter方法和toString
}
3.2 实现Externalizable
接口
实现Externalizable
接口必须重写连个方法
writeExternal(ObjectOutput out)
readExternal(ObjectInput in)
public class TextBean implements Externalizable {
private Integer id;
private String name;
private Date date;
//可以自定义决定那些需要序列化
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(id);
out.writeObject(name);
out.writeObject(date);
}
//可以自定义决定那些需要反序列化
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.id = in.readInt();
this.name = (String) in.readObject();
this.date = (Date) in.readObject();
}
//省去getter和setter方法和toString
}
3.3 serialVersionUID
的作用
先讲述下序列化的过程:在进行序列化时,会把当前类的serialVersionUID
写入到字节序列中(也会写入序列化的文件中),在反序列化时会将字节流中的serialVersionUID
同本地对象中的serialVersionUID
进行对比,一直的话进行反序列化,不一致则失败报错(报InvalidCastException
异常)
serialVersionUID
的生成有三种方式(private static final long serialVersionUID= XXXL
):
- 显式声明:默认的 1 L
- 显式声明:根据包名、类名、继承关系、非私有的方法和属性以及参数、返回值等诸多因素计算出的64位的hash值
- 隐式声明:未显式的声明
serialVersionUID
时java
序列化机制会根据Class自动生成一个serialVersionUID
(最好不要这样,因为如果Class发生变化,自动生成的serialVersionUID
可能会随之发生变化,导致匹配不上)