Serializable接口和serialVersionUID成员变量的作用

相关概念:

*Serializable接口是一种标记性接口,即它没有方法,实现这个接口可以启动Java的序列化机制,自动完成存储对象和数组的过程。

*Java提供一个内在机制完成写对象的过程,这过程称为:对象序列化(Object serialization),它是在ObjectOutputStream中实现的;

*与此相反,读取对象的过程称为:对象反序列化(Object deserialization),它是在ObjectInputStream类中实现的;

*许多Java API中的类都实现了Serializable接口,如工具类Java.util.Date以及所有Swing GUI 组件都实现了Serializable接口;

*试图存储一个不支持Serializable接口的对象会引起一个NotSerializableException异常。

*当存储一个可序列化对象时,会对该对象的类进行编码:包括类名、类的签名、对象实例变量的值以及从初始对象引用的任何其他对象的闭包,但不存储对象静态变量的值。

用法:
一、首先明白什么是序列化
我们经常看到一个实体类实现Serializable接口,这种用法就是序列化。目的是保存对象的状态,以便将它读取出来。
序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。
序列化将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例
Java为我们提供一种比较好的保存对象状态的机制,那就是序列化。
也就是说,保存状态和读取状态的事java已经帮我们做了,我们只需调相应的方法就可以了。

二、序列化有什么特点
如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。static代表类的状态, transient代表对象的临时数据。

三、什么情况下需要实例化
 1、当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
 2、当你想用套接字在网络上传送对象的时候;
 java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
 3、当你想通过RMI传输对象的时候;
 RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。

 

一般情况下,我们在定义实体类时会继承Serializable接口,类似这样:

我们在实体类中引用了Serializable这个接口,那么这个接口到底有什么?细心的你会发现我们还定义了个serialVersionUID变量。这个变量到底有什么作用?

什么是Serializable接口?

一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。

什么是序列化?

序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。

为什么要序列化对象?

①把对象转换为字节序列的过程称为对象的序列化

②把字节序列恢复为对象的过程称为对象的反序列化

什么情况下需要序列化?

当我们需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化

那为什么还要继承Serializable。那是存储对象在存储介质中,以便在下次使用的时候,可以很快捷的重建一个副本。

或许你会问,我在开发过程中,实体并没有实现序列化,但我同样可以将数据保存到mysql、Oracle数据库中,为什么非要序列化才能存储呢?

我们来看看Serializable到底是什么,跟进去看一下,我们发现Serializable接口里面竟然什么都没有,只是个空接口

一个接口里面什么内容都没有,我们可以将它理解成一个标识接口。

比如在课堂上有位学生遇到一个问题,于是举手向老师请教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,自己解决不了问题请教老师帮忙解决。在Java中的这个Serializable接口其实是给jvm看的,通知jvm,我不对这个类做序列化了,你(jvm)帮我序列化就好了。

Serializable接口就是Java提供用来进行高效率的异地共享实例对象的机制,实现这个接口即可。

什么是JVM?

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

为什么要定义serialversionUID变量??

从说明中我们可以看到,如果我们没有自己声明一个serialVersionUID变量,接口会默认生成一个serialVersionUID

However, it is <em>strongly recommended</em> that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected<code>InvalidClassException</code>s during deserialization.

但是强烈建议用户自定义一个serialVersionUID,因为默认的serialVersinUID对于class的细节非常敏感,反序列化时可能会导致InvalidClassException这个异常。

在前面我们已经新建了一个实体类User实现Serializable接口,并且定义了serialVersionUID变量。

我们把User写到文件,然后读取出来。

 

 

是的,你没有看错,序列化与反序列化操作过程就是这么的简单。只需要将User写入到文件中,然后再从文件中进行恢复,恢复后得到的内容与之前完全一样,但是两者是不同的对象。前面提到过一个问题,如果将serialVersionUID变量去掉,我们来看看,会发生什么事情。

刚开始提到了,serialVersionUID要不要指定呢?如果不指定会出现什么样的后果?如果指定了以后后边的值又代表着什么意思呢?既然系统指定了这个字段,那么肯定是有它的作用的。

这个serialVersionUID是用来辅助对象的序列化与反序列化的,原则上序列化后的数据当中的serialVersionUID与当前类当中的serialVersionUID一致,那么该对象才能被反序列化成功。这个serialVersionUID的详细的工作机制是:在序列化的时候系统将serialVersionUID写入到序列化的文件中去,当反序列化的时候系统会先去检测文件中的serialVersionUID是否跟当前的文件的serialVersionUID是否一致,如果一直则反序列化成功,否则就说明当前类跟序列化后的类发生了变化,比如是成员变量的数量或者是类型发生了变化,那么在反序列化时就会发生crash,并且回报出错误:

java.io.InvalidClassException: User; local class incompatible: stream classdesc serialVersionUID = -1451587475819212328, local class serialVersionUID = -3946714849072033140at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)at Main.readUser(Main.java:32)at Main.main(Main.java:10)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值