Java序列化与反序列化
由于没有实战的经验,对于这方面的记录,重点放在“序列化”的理解上…
问题引入
1、对象的状态不能长久的保存:(例如 )Java程序运行时,对象存储在堆内存中,会被当成垃圾回收,或者程序运行结束,对象的状态无法长久保存
2、超级多个对象耗费内存空间:(例如 )Web服务器上Session对象,相当多的用户并发访问,有N个用户,就有N个Session对象,十分耗费内存
……
序列化引入
从上述问题中可以发现,问题主要集中在对象和内存(RAM)上,要么是存活时间短,要么是对象太多,耗费空间,那么将内存中的对象存放在硬盘上或其他存储介质上,能够持久化存储是不是就解决了这个问题呢?
1、对象的状态持久保存,即使程序结束,下次使用时,仍是上次结束时的状态
2、多个对象存储在硬盘或其他存储介质上,缓解了内存消耗的压力
……
什么是序列化
在数据储存与传送的部分是指将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等,或者透过网络传送资料时进行编码的过程,可以是字节或是XML等格式。而字节的或XML编码格式可以还原完全相等的对象。这程序被应用在不同应用程序之间传送对象,以及服务器将对象储存到档案或数据库。相反的过程又称为反序列化(来源:维基百科)
综上所述,那么我的个人理解:
将内存中对象按照字节或xml,json等格式编码成二进制序列的过程叫做序列化
将存储介质中的二进制序列按照字节或xml,json等格式还原出对象的过程叫做反序列化
对象的状态
说了很久的对象的状态,那么什么是对象的状态呢?
对象的状态:就是对象中的成员变量
序列化的作用
1、对象永久保存在存储介质上
2、便于远程进程之间对象数据的传输
以上是简单的文字描述,下面图、码描述
示例
需求:有个一对象(new Person()),我们需要持久化这个对象的状态信息(已经理解对象的状态了吗?)
public class Person{ private String name; private int age; //getter() 和 setter() 方法 public void setName(String name){this.name = name;} public String getName(){return this.name;} public void setAge(int age){this.age = age;} public int getAge(){return this.age;} }
很简单的一个Person类,只有两个成员变量:name 和 age ;
其实,我们也很好理解对象的状态就是对象的成员变量,我们拿我们一个人来说,把人看作一个对象,我们的姓名,年龄,身高,体重等等,
这些属性会随着时间的推移而改变,那么不同时刻我们的这些成员属性是不是就是我们这个人的对象在某一时刻的状态呢?
相关API
默认序列化 接口:Serializable(标记接口),该接口只用于标记实现它的类是可序列化的,内部无方法 类:ObjectOutputStream 和 ObjectInputStream
上述需求的代码实现
类Person.java package com.java; import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
类ObjectSerializable.java package com.java; import java.io.*; public class ObjectSerializable { public static void main(String[] args) { writeObj(); readObj(); } /** * 序列化对象 */ private static void writeObj() { try { ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("E://person.object")); Person person = new Person(); person.setName("ZhangSan"); person.setAge(22); oos.writeObject(person); oos.close(); System.out.println("写出成功...."); } catch (IOException e) { e.printStackTrace(); } } /** * 反序列化对象 */ private static void readObj() { try { ObjectInputStream ois = new ObjectInputStream(new FileInputStream( "E://person.object")); //反序列化还原对象 Person person = (Person) ois.readObject(); System.out.println(person.getName()); System.out.println(person.getAge()); ois.close(); System.out.println("读入成功..."); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
注意:序列化与反序列化是个互逆的过程
在执行writeObj()方法的时候,先注释掉readObj(),即执行序列化操作
在执行readObj()方法的时候,先注释掉writeObj(),即执行反序列化操作
图示
![](http://i.imgur.com/NHZVuTQ.png)
对象的状态示意图
![](http://i.imgur.com/HPv16PY.png)
序列化示意图
![](http://i.imgur.com/yL5JyaL.png)
反序列化示意图
注意:序列化后的内容,是用文本编辑器按照GBK的编码格式打开后的效果
总结
1、以上是我对Java序列化一些简单理解,水平有限,只为记录分享,如有错误,欢迎批评指正…
2、本文主要是对于序列化的理解记忆,并不涉及具体的使用,比如serializable接口,另外两个类,还有serialVersionUID的使用,以及transient关键字,Externalizable接口,读者可参考下面给出的我参考的资料。
3、由于时间关系,内容不够完善,后续会继续完善
参考(感谢)
1、http://blog.csdn.net/u011303467/article/details/9256647
2、http://developer.51cto.com/art/201202/317181.htm
3、http://blog.csdn.net/jiangwei0910410003/article/details/18989711