一 java序列化操作的基本原理
1,什么序列化和反序列化
serialization(序列化),是一种将对象按照一定规则生成出一连串有序的字符的过程。这个一连串有序的字符 可以是二进制, xml,json,或特定的字符串 等等。
Deserialization(反序列化) 将 一连串有序的字符 --》对象
2,什么情况下需要序列化
a) 当你想把一个内存中对象保存到一个文件中或数据库中的时候(持久化)
b)在跨平台的环境下,通过网络传输对象时(WebSerivce SOAP)
c)当通过RMI传出对象的时候(仅限于java环境)
3,如何实现序列化
需要实现序列化的类实现 serialization接口。 Serialization接口中无任何方法,所以我们可以理解为一个标记,表明这个类可以被序列化
4,Serializable的作用
仅仅是个标记而已
5,序列化和反序列化例子
public class demo { //序列化Student对象至outFile文件 public static void serialize(Object obj, String outFile) { try { ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(outFile)); oos.writeObject(obj); oos.flush(); oos.close(); } catch (Exception e) { e.printStackTrace(); } } //将outFile文件中的内容反序列化为Student对象 public static Object deserialize(String readFile) { try { ObjectInputStream oos=new ObjectInputStream(new FileInputStream(readFile)); Object obj=oos.readObject(); oos.close(); return obj; } catch (Exception e) { e.printStackTrace(); } return null; } public static void main(String[] args) { Student stu=new Student("tengxvincent",18); String stuFileName="student.out"; //serialize(stu,stuFileName); Student student= (Student)deserialize(stuFileName); System.out.println(student); } }
6,默认序列化机制
7,影响序列化
7.1 transient关键字
对于一些敏感的关键字(用户密码)可以用 transient 修饰该字段 不去序列化
7.2 静态变量是否能序列化 为什么?
不能序列化
7.3 writeObject()方法与readObject()方法
//jdk自动调用, 扩展序列化规则的一个方法 //打破serialization接口序列化规则 private void wirteObject(ObjectOutputStream out) throws IOException { // TODO Auto-generated method stub out.defaultWriteObject(); out.writeInt(age); } private void readObject(ObjectInputStream in)throws IOException,ClassNotFoundException { // TODO Auto-generated method stub in.defaultReadObject(); age=in.readInt(); }
对于transient关键字修饰的字段 可以使用这两个方法 序列化
7.4 Externalizable接口
/** * * 如果实现这个接口,jdk将不会调用默认的序列化规则,完全使用自定义的序列化规则 */ public class Person implements Externalizable { private String name; transient private int age; //扩展序列化规则的方法 @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // TODO Auto-generated method stub name=(String)in.readObject(); age=in.readInt(); } @Override public void writeExternal(ObjectOutput out) throws IOException { // TODO Auto-generated method stub out.writeObject(name); out.writeInt(age); }
7.5 readResolve()方法
当我们使用单例模式时,应该是期望这个类的实例是唯一的,但是如果该类是可实例化的,那么情况可能就不一样,
此时,我能可以使用 readResove()方法的实现,来确保在同一jvm中只有一个单例对象的引用
public class Message implements Serializable{ private String name; private int age; private Message(String name,int age) { this.name=name; this.age=age; } /** * @return 获取一个单例对象 */ public static Message getInstance() { return InstanceHolder.instance; } private static class InstanceHolder{ private static final Message instance=new Message("呵呵",18); } private Object readResolve() { return InstanceHolder.instance; } }
8 序列化ID
主要是针对跨平台,跨服务器,如果序列化ID不一致,会导致无法反序列化
9 序列化前和序列化后的对象的关系?
是==还是 equals 是浅克隆还是深克隆?
msgpack序列化与json序列化方式的比较