实体类实现 Serializable
应用场景定义实体类时会继承Serializable接口import java.io.Serializable;public class PK implements Serializable {private static final long serialVersionUID=1L;}作用Serializable是一个对象序列化的接口。一个类只有实现了Serializable接口,它的对象才能被序
应用场景
定义实体类时会继承Serializable接口
import java.io.Serializable;
public class PK implements Serializable {
private static final long serialVersionUID=1L;
}
作用
Serializable是一个对象序列化的接口。一个类只有实现了Serializable接口,它的对象才能被序列化。
序列化
定义
把对象转换为字节序列的过程称为对象的序列化;
把字节序列恢复为对象的过程称为对象的反序列化。
用途
当我们需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化。
网络上传输的都是二进制,不会直接传输对象。
我在开发过程中,实体并没有实现序列化,但我同样可以将数据保存到mysql、Oracle数据库中,为什么非要序列化才能存储呢?
int、long、boolean类型等,都是基本数据类型,数据库里面有与之对应的数据结构。从类声明来看,我们以为的没有进行序列化,其实是在声明的各个不同变量的时候,由具体的数据类型帮助我们实现了序列化操作。所以就算我们不实现serializable依旧可以正常操作。序列化操作用于存储时,一般是对于NoSql数据库。
实现
Serializable接口是一个空接口,相当于一个标识,通知jvm,我不对这个类做序列化了,你(jvm)帮我序列化就好了。
SerialVersionUID
对于JVM来说,要进行持久化的类必须要有一个标记,只有持有这个标记JVM才允许类创建的对象可以通过其IO系统转换为字节数据,从而实现持久化,而这个标记就是Serializable接口。而在反序列化的过程中则需要使用serialVersionUID来确定由那个类来加载这个对象,所以我们在实现Serializable接口的时候,一般还会要去尽量显示地定义serialVersionUID,如:
private static final long serialVersionUID = 1L;
在反序列化的过程中,如果接收方为对象加载了一个类,如果该对象的serialVersionUID与对应持久化时的类不同,那么反序列化的过程中将会导致InvalidClassException异常。例如,在之前反序列化的例子中,我们故意将User类的serialVersionUID改为2L,如:
private static final long serialVersionUID = 2L;
那么此时,在反序例化时就会导致异常,如下:
java.io.InvalidClassException: cn.wudimanong.serializable.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1880) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1746) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2037) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428) at cn.wudimanong.serializable.SerializableTest.readObj(SerializableTest.java:31) at cn.wudimanong.serializable.SerializableTest.main(SerializableTest.java:44)
如果我们在序列化中没有显示地声明serialVersionUID,则序列化运行时将会根据该类的各个方面计算该类默认的serialVersionUID值。但是,Java官方强烈建议所有要序列化的类都显示地声明serialVersionUID字段,因为如果高度依赖于JVM默认生成serialVersionUID,可能会导致其与编译器的实现细节耦合,这样可能会导致在反序列化的过程中发生意外的InvalidClassException异常。因此,为了保证跨不同Java编译器实现的serialVersionUID值的一致,实现Serializable接口的必须显示地声明serialVersionUID字段。
此外serialVersionUID字段地声明要尽可能使用private关键字修饰,这是因为该字段的声明只适用于声明的类,该字段作为成员变量被子类继承是没有用处的!有个特殊的地方需要注意的是,数组类是不能显示地声明serialVersionUID的,因为它们始终具有默认计算的值,不过数组类反序列化过程中也是放弃了匹配serialVersionUID值的要求。
更多推荐
所有评论(0)