网站建设的计划书,索菲亚全屋定制官方网站,代码错误网站,网站建设定制公众号小程序序列化和反序列化序列化和反序列化作用为什么需要用途Serializable使用serialVersionUID不设置的后果什么时候修改Externalizable序列化的顺序json序列化序列化和反序列化
序列化#xff1a;把对象转换为字节序列的过程称为对象的序列化。 反序列化:把字节序列恢复为对象的过…
序列化和反序列化序列化和反序列化作用为什么需要用途Serializable使用serialVersionUID不设置的后果什么时候修改Externalizable序列化的顺序json序列化序列化和反序列化
序列化把对象转换为字节序列的过程称为对象的序列化。 反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
其实就是将代码中运行的对象从内存中保存为字节序列可以存储和传输。
作用
把对象的字节序列永久地保存到硬盘上通常存放在一个文件中在网络上传送对象的字节序列。
为什么需要
Java对象是运行在JVM的堆内存中的如果JVM停止后它的生命也就戛然而止。 如果想在JVM停止后把这些对象如何保存起来呢。我们只能保存到硬盘上或者传输到其他地方了但是很多硬件或者说传输只支持二进制而不认识java的对象所以需要将这些对象转换成字节序列了。 我感觉和高级语言编译成二进制差不多。java对象是我们好理解的二进制是机器理解的。
用途
可以做对象的备份会恢复兼容性规定数据存储保存到数据库、文件等传输
怎么样序列化需要我们来规定所以学习这些规定的方法 如果不规定则会报错 MyArrayList 是自己实现的一个动态数组的类还未实现Serializable接口
public void testSerializable() {MyArrayList list new MyArrayList();for (int i 0; i 100; i) {list.add(i);}try(ObjectOutputStream o new ObjectOutputStream(new FileOutputStream(a.txt));ObjectInputStream in new ObjectInputStream(new FileInputStream(a.txt));) {o.writeObject(list);MyArrayList l (MyArrayList) in.readObject();System.out.println(l);} catch (IOException | ClassNotFoundException e) {throw new RuntimeException(e);}
}会出现这样的错误
Serializable
Serializable接口是一个标记接口没有方法或字段。一旦实现了此接口就标志该类的对象就是可序列化的。 这种是隐式序列化(不需要手动)这种是最简单的序列化方式会自动序列化所有非static和 transient关键字修饰的成员变量
使用
实现之后在运行上面代码 a.txt,看不懂的
serialVersionUID
意思就是序列化版本号ID其实每一个实现Serializable接口的类都有一个表示序列化版本标识符的静态变量或者默认等于1L或者等于对象的哈希码。
JAVA序列化的机制是通过判断类的serialVersionUID来验证版本是否一致的。在进行反序列化时会把serialVersionUID和本地相应实体类的serialVersionUID进行比较如果相同反序列化成功如果不相同就抛出InvalidClassException异常。 修改一下在读取记得注释掉序列化的代码
不设置的后果
在类中新增一个不使用的字段 然后序列化后删除这个字段 我们会发现其报错
Caused by: java.io.InvalidClassException:
com.yu.MyArrayList; local class incompatible:stream classdesc serialVersionUID 8278873907900787181, local class serialVersionUID -9196603521067733754我们不是没有设置这个字段吗怎么报错会显示这个呢。这个是怎么来的
在没有定义 serialVersionUID的时候就会生成默认的序列化唯一标示。
他的生成规则是根据类名方法和属性等参数生成的 hash 值所以在删除后其hash值会改变。 但是这个字段对于我们来说毫无影响所以我们可以自行设置serialVersionUID 的值 在进行上面操作且不修改serialVersionUID 的值会发现代码通过了。
什么时候修改
在阿里巴巴开发手册中有 不是说一定不能修改在不兼容的时候在修改。
就像上面的这个字段对代码毫无影响那么我们就不需要修改了。
这个应该强制一下实现了这个接口的就必须赋初值不然随便修改一下属性就不能反序列化了。这就是差不多是一个兼容性问题就像各个版本的JDK代码都拿出来看一下那些向下兼容的类的serialVersionUID是没有变化过的。
Externalizable
Externalizable继承了Serializable接口还定义了两个抽象方法writeExternal()和readExternal()如果开发人员使用Externalizable来实现序列化和反序列化需要重写writeExternal()和readExternal()方法 这2个方法给定了流直接调用流的方法自定义读和写就行
如我什么都不序列化获取里面的大小就是0 只序列化大小
如果我序列化大小和容量打印数据就会报错。 因为我们的类中的数组没有这么大初始为空所以会报错。
序列化的顺序
那么我们如果重复序列化size会发生什么 获取其中的size和capacity
我们来混乱的定义 打印结果 可以看到顺序和我们序列化的顺序一样和属性无关
最后我们用不同属性进行 发现了几点规律 接收和发送顺序完全一样不会是int读intobject读object。 顺序错了会报错
不同类型混合接收 至于为什么是这样应该涉及太底层的我还不知道到时候看流的底层的时候在看看。
json序列化
json使用就比较简单 但是会报错。 这里看到只序列化了size。 因为fastjson会扫描其中的getter方法我们只设置了getSize方法。 所以其他的访问不到。 json的具体内容以后在说这里只介绍其普通使用。