一.java序列化的用途
1.将数据持久化到文件中
2.在网络上传输字节序列
两种功能的示意图如下:
二.实现对象序列化的条件
1. 只有实现了Serializable(默认的序列化方式)或Externalizable(继承Serializable接口,自定义实现来控制序列化时的行为)接口的类才能被序列化.
2..利用java.io.ObjectOutputStream类的writeObject(Object obj)来实现对象序列化操作,并将字节序列写入到到目标输出流中.利用它的readObject()方法从源输入流中读取字节流,再将数据反序列化成一个对象并返回该对象.
三.通过实现Serializable接口序列化.和反序列化
1.如果类A实现了Serializable接口,则对类A的非static,非transient的实例变量进行序列化和反序列化
此方法不能控制序列化时的行为.以下两种方法则行.
2.如果类A既实现了Serializable接口,又定义了writeObject(Object obj)方法和readObject()方法,由调用这两个方法进行序列化和反序列化.
3.如果类A实现了Externalizable接口,由该类必须实现writeExternal(ObjectOutput out)方法和readExtername()方法.在这种情况下,将按照这两个方法进行对象的序列化和反序列化.
四.对象序列化和对象反序列化的步骤
对象序列化步骤:
1.创建一个对象输出流
2.通过对象输出流的writeObject(Objectobj)方法写对象
如:
ObjectOutputStream out = newObjectOutputStream(new FileOutputStream(filePath));//filePath:文件路径
out.writeObject(obj);//obj:要写入文件的对象
对象反序列化步骤:
1.创建一个对象输入流
2.通过对象输入流的readObject(j)方法读取对象.(读取对象时是按照对列方式进行的,既先进先出)
如:
ObjectInputStream in = new ObjectInputStream (newFileInputStream(filePath));
in.readObject();//读取对象
五.对于实现了Serializable接口反序列化过程
1.如果内存中的对象所属的类还没有加载,则先加载并初始化这个类,如果在classpath中找不到这个类,则抛出ClassNotFoundException
2.在反序列化时,不能调用类的任何构造方法.
3.如果此类引用了其他类或者关联了其他类,则在序列化时,将同时序列化它所引用的类.
六. Serializable接口下控制序列化行为
1.实现Serializable接口,并提供private void writeObject(Object obj),private void readObject()方法.如果需要默认序列化方法或者默认反序列化方法,则可以在这两个方法中调用ObjectOutputStream的defaultWriteObject()方法或者ObjectOutputStream的defaultReadObject()方法
2.如何确定需要用户自定义序列化方式,从而控制序列化的行为,如下所示:
>确保序列化的安全性,对敏感信息的隐藏者加密.如果序列化加密,则反序列化时要解密.
>确保对象的成员变量符合正解的约束条件
>优化序列化的性能.主要是避免过多序列化类的关联类.
>便于更好地封装类的内部数据,确保类的接口不会被类的内部实现所约束.
七.实现Externalizable接口
1.实现此接口的类必须自己控制序列化和反序列化时的行为.因此必须实现public void writeExternal(ObjectOutput out)方法和public void readExtername()方法.在对实现了Externalizable接口的类进行反序列化时,会先调用类的不带参数的构造方法,这是有别于默认反序列化方式的.所以类必须要有一个public访问权限的不带参数的构造方法.
八.可序列化类的不同版本的序列化兼容性
对于同一个类的两个不同版本,即便它们的序列化版本号相同,也不一定能兼容.因为兼容性不仅取决于序列化版本号,还取决于类的不同版本的实现细节和序列化细节.