序列化是什么
在刚开始接触这一概念时,是有点懵的,为啥要把对象存下来,不是有类么,还有啥反序列化,这都啥跟啥呀。大概浏览完序列化这一块的知识之后,想了一会儿,大致是弄懂了具体是怎么玩的了。
想想这样一个场景,我创建了一个对象,或者由什么方法得到了一个对象,这个对象来之不易,那么,如果我们一个小组的其他成员也需要用这个对象呢,我怎么让她也能使用这个对象呢。(抓耳挠腮)此时,序列化这个出现救命了,我们把自己手中的对象直接打包成文件,拷贝给她,通过网络或者whatever方式传输,这样就很是方便。把对象打包成文件叫做序列化。
还有一个场景就是,下次,我也想使用这个对象怎么办,那么不如把它保存起来,留着下次用,免得再创建一次。
对应的,她把我传输的的对象文件恢复成对象的模样,就是反序列化。
序列化的使用过程
使用步骤:
- 创建ObjectOutputStream对象,构造方法中传递字节输出流
- 使用对象中的方法writeObject,把对象写入到文件中
- 释放资源
其中,序列化流输出对象其实用到了字节输出流,因为它要把对象以字节的形式写入文件,写完文件记得释放资源哦,养成好习惯
反序列化的使用步骤也跟上面大同小异,其中接收反序列化的对象一般用object类,具体使用时再向下强制类型转换即可。具体使用请参照API文档,这里不做赘述
注意要点
- 在使用序列化与反序列化时,可能会出现SerializationException: could not
serialize的异常提示,这是因为序列化要求被打包的类需要实现serializable接口,你没有实现这个接口当然要出异常了。什么,还要出异常,还要实现接口,那我不用了,告辞!哎回来回来,这个接口不用实现的,emmmm也不是不用实现,是不用实现接口中的方法。serializable接口是一个标记接口,查看源码我们可以发现,它里面什么方法都没有,没有抽象方法,也没有默认方法,标记接口不是java语法,而是一种设计理念,具体做什么用嘛我也没有深究,姑且放这,如果以后真能碰的上,那么回来再看。这里,只需要implement
一下serializable接口就可以消除异常啦。 - 第二个注意点就是static关键字,被这个关键字修饰的成员变量是不能被序列化的,应该说它的值是不能被打包放在文件中的,所以反序列化后,这个成员变量的值不是之前的值,而是默认值。consistent关键字在此与static关键字的作用一模一样,如果你只是不希望这个成员变量的值被打包,而不希望它具有静态性质,那么就使用consistent吧。关于不能序列化的用途,我是这样想的,假设你要是有些数据不想让别人用呢,那咋办,用consistent关键字就好了。
- 最后一个比较关键的点就是序列号。
当我们编译一个类代码文件后,会生成一个字节码文件(.class),根据字节码文件的内容,它会有一个序列号,具体怎么生成,哎,哈希,哈希就完事了。当我们对该类对象进行序列化后得到对象文件,它也有序列号,而且就是字节码文件的序列号,二者相同。当类代码改变时,字节码文件也会改变,其对应序列号也会改变,此时反序列化,对象文件的序列号与字节码的序列号不相符,就会出现错误。
或许会想,为什么要弄这样一个序列号呀。序列号是用来验证版本一致的,那有人要问,什么是版本一致呢,那我就不知道了,我是新手呢。至于解决办法,就是在被打包的类中定义版本号为静态成员变量
public static final Long seriaVersionUID = XXXL;如此操作,就可以解决我可能序列化之后还要修改类的问题了。