加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

Java对象为啥要实现Serializable接口?

发布时间:2019-05-15 01:13:12 所属栏目:优化 来源:无敌码农
导读:导读 最近这段时间一直在忙着编写Java业务代码,麻木地搬着Ctrl-C、Ctrl-V的砖,在不知道重复了多少次定义Java实体对象时implements Serializable的C/V大法后,脑海中突然冒出一个思维(A):问了自己一句Java实体对象为什么一定要实现Serializable接口呢?,

对于JVM来说,要进行持久化的类必须要有一个标记,只有持有这个标记JVM才允许类创建的对象可以通过其IO系统转换为字节数据,从而实现持久化,而这个标记就是Serializable接口。而在反序列化的过程中则需要使用serialVersionUID来确定由那个类来加载这个对象,所以我们在实现Serializable接口的时候,一般还会要去尽量显示地定义serialVersionUID,如:

  1. private static final long serialVersionUID = 1L; 

在反序列化的过程中,如果接收方为对象加载了一个类,如果该对象的serialVersionUID与对应持久化时的类不同,那么反序列化的过程中将会导致InvalidClassException异常。例如,在之前反序列化的例子中,我们故意将User类的serialVersionUID改为2L,如:

  1. private static final long serialVersionUID = 2L; 

那么此时,在反序例化时就会导致异常,如下:

  1. java.io.InvalidClassException: cn.wudimanong.serializable.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2 
  2.     at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687) 
  3.     at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1880) 
  4.     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1746) 
  5.     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2037) 
  6.     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568) 
  7.     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428) 
  8.     at cn.wudimanong.serializable.SerializableTest.readObj(SerializableTest.java:31) 
  9.     at cn.wudimanong.serializable.SerializableTest.main(SerializableTest.java:44) 

如果我们在序列化中没有显示地声明serialVersionUID,则序列化运行时将会根据该类的各个方面计算该类默认的serialVersionUID值。但是,Java官方强烈建议所有要序列化的类都显示地声明serialVersionUID字段,因为如果高度依赖于JVM默认生成serialVersionUID,可能会导致其与编译器的实现细节耦合,这样可能会导致在反序列化的过程中发生意外的InvalidClassException异常。因此,为了保证跨不同Java编译器实现的serialVersionUID值的一致,实现Serializable接口的必须显示地声明serialVersionUID字段。

此外serialVersionUID字段地声明要尽可能使用private关键字修饰,这是因为该字段的声明只适用于声明的类,该字段作为成员变量被子类继承是没有用处的!有个特殊的地方需要注意的是,数组类是不能显示地声明serialVersionUID的,因为它们始终具有默认计算的值,不过数组类反序列化过程中也是放弃了匹配serialVersionUID值的要求。

参考资料:

https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true

http://www.tutorialspoint.com/java/java_serialization.htm

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读