【Java基础】——序列化与反序列化

 何为序列化?

序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。对象序列化机制允许把内存中Java对象转换成平台无关二进制流,从而允许把这种二进制流持久地保存在磁盘上,或者将这种二进制流传输到另一个网络节点,其他程序获得这种二进制流,都可以将二进制流恢复成原来的Java对象。序列化机制使得对象可以脱离程序的运行而独立存在。

所谓的对象序列化将一个Java对象写入IO流中转为字节流,反序列化则指从IO流中将字节流恢复该对象,注意静态常量不会被默认序列化。

序列化两种机制

Java中让某个对象支持序列化机制,必须让它的类是可序列化,为了让类是可序列化,则该类必须实现如下两接口之一

Serializable

Externalizable

所在可能在网络上传输的对象的类都应该是可序列化的,否则程序会出现异常。序列化是RMI必须实现的机制,而目前大部分程序都是分布式,需要跨平台,跨网络,所以通常建议:程序创建的每个JavaBean类都实现序列化接口。

实现Serializable接口

使用方式非常简单,目标类实现Serializable即可,无需实现任何方法。一旦实现Serializable接口,则该类的对象就是可序列化的。

Serializable是一个没有定义任何方法的标记接口,但是声明Serializable接口后保存读取对象就可以使用ObjectOutputStream,ObjectInputStream流了。ObjectOutputStream 是 OutputStream 的子类,但实现了 ObjectOutput 接口,ObjectOutput 是 DataOutput 的子接口,增加了一个 writeObject(Object obj) 方法将对象转化为字节写到流中,ObjectInputStream 是 InputStream 的子类,实现了ObjectInput 接口,ObjectInput 是 DataInput 的子接口,增加了一个 readObject() 方法从流中读取字节转为对象,序列化和反序列化的实质在于 ObjectOutputStream 的 writeObject 和 ObjectInputStream 的 readObject 方法实现。Serializable虽然是一个空接口,但是在调用writeObject方法时却充当了一种健全的校验作用。如果对象没有实现Serializable接口则在调用writeObject时抛出异常,Serializable算是一种接口标识机制。

自定义序列

有些时候对象中某些字段可能与内存位置,或者时间有关,序列化后没有太大实际意义,或者有些敏感信息(工资,银行密码)之类的内容不方便在网络传输默认序列化不合适,需要定制序列化。Java中提供关键字transient关键字,如果成员变量被transient修饰则不会被序列化。有些时候需要自定义序列方式,可以采用在类中自定义实现writeObject和readObject方法。

版本问题

默认情况下Java会根据类中信息自动生成一个版本号,如果反序列化时如果类发生了变化版本号就变化,也就与反序列化流中的版本号不匹配导致会抛出异常,所以我们为了更好的控制和性能问题会自定义 serialVersionUID 版本号来避免类定义发生变化后反序列化版本号不匹配异常问题,如果版本号一样时流中有该字段而类定义中没有则该字段会被忽略,如果类定义中有而流中没有则该字段会被设为默认值,如果对于同名的字段类型变了则会抛出 InvalidClassException。

虚拟机是否允许反序列化不仅取决于类路径和功能代码是否一致,还取决于另一个非常重要的点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mandy_i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值