Serializable 接口与 Java 序列化与反序列化
2017-09-12 00:01
441 查看
0. 序列化的意义
从内存到本地即为本地化或者在网络中进行传输,或叫序列化,持久化。某 Java 类实现 Serializable 接口的目的是为了可持久化(简单理解为本地化),比如网络传输或本地存储,为系统的分布式运行和异构部署提供先决支持条件。若没有序列化,我们熟悉的远程调用(RPC,无法读取远程主机内存中的任何目标,必须首选在远程将目标序列化),对象数据库都不可能存在。
1. 一个简单 demo
Serializable 为空接口,只是为了起到标识说明之义。Person 类实现 Serializable 接口,这是一个简单的 JavaBean,实现了 Serializable 接口,可以在网络上传输,也可以本地存储然后读取。我们可以通过 Java 消息服务(Java Message Service)方式传递该对象(即通过网络传递一个对象),定义在消息队列中的数据类型为 ObjectMessage。
public class Person implements Serializable { private String name; // 省略 getter、setter }
序列化及反序列化客户端代码:
public class Producer { final static String FILE_NAME = "C:/obj.bin"; public static void main(String[] args) { Person person = new Person(); person.setName(""); SerializationUtils.writeObject(person, FILE_NAME); } } public class Conducer { final static String FILE_NAME = "C:/obj.bin"; public static void main(String[] args) { Person p = (Person)SerializationUtils.readObject(FILE_NAME); p.getName(); } }
其中的 SerializationUtils 工具类如下:
public class SerializationUtils { // 序列化 public static void writeObject(Serializable s, String filename) { try { ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(filename)); oos.writeObject(s); oos.close(); } catch (Exception e) { e.printStackTrace(); } } // 反序列化 public static Object readObject(String filename) { Object obj = null; try { ObjectInputStream ois = new ObjectInputStream( new FileInputStream(filename)); ois.readObject(); ois.close(); } catch (Exception e) { e.printStackTrace(); } return obj; } }
2. UID 的必要性
正因为分布和异构,无论是读取本地文件还是远程调用,本地是无法在编译期获取待获取的类的完整信息的(成员变量和函数)。也即有可能发生,消息的生产者和消息的消费者所参考的类(Person)有差异,比如消息生产者的 Person 类添加一个年龄字段,而相应的消费者没有增加该属性。这种序列化和反序列化的类不一致的情形下,反序列时有可能会报一个 InvalidClassException 异常。原因就在于序列化和反序列化所对应的类版本发生了变化,JVM 不能把数据流转换为实例对象。那么,JVM 是根据什么来判断一个类版本的呢?
通过 SerialVersionUID,也叫流标志符(Stream Unique Identifier)。
public class Person implements Serializable { private static final long serialVersionUID = 55799L; }
此时如果发生如下形式的不一致的情况,生产者增加年龄属性,消费端 Person 还保持以前的版本。此时,虽然物理上,生产者和消费者对应的类版本不同,但是显式声明的 serialVersionUID 相同,反序列化也可以运行,所带来的业务问题即是消费端无法读取新增的业务属性。
相关文章推荐
- Java中实现序列化的两种方式 Serializable 接口和 Externalizable接口
- java基础问题---什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
- java为什么只有实现了Serializable接口才可以序列化
- 理解Java对象序列化——Serializable接口
- 什么是java序列化,如何实现java序列化?或请解释Serializable接口的作用
- java.io.Serializable (序列化接口)
- java对象序列化java.io.Serializable 接口实践
- 面试题:Java中对象序列化接口(Serializable)的意义
- Java的Serializable序列化接口的readObject和writeObject方法
- Android 对象序列化 Java中实现Serializable序列化与Android特有的实现Parceable接口序列化操作
- 面试题:Java中对象序列化接口(Serializable)的意义
- java中实现序列化serializable接口的问题
- java的序列化或Serializable接口的作用
- java:序列化Serializable 接口
- java.io.Serializable(序列化)接口详细总结
- java序列化接口Serializable的使用
- Java中序列化接口Serializable接口的作用
- java序列化接口Serializable
- 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
- 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用