鸟菜基础篇_2012_8_26序列化

来源:互联网 发布:心理学书籍 人格 知乎 编辑:程序博客网 时间:2024/05/16 05:19

本期鸟菜谈谈序列化吧,很实用的技术点,操作起来也很简单。

1. 序列化Serialize实质上就是将“对象”按照某种规则封装成特定的字节流,这种字节流被同样的规则解析后在,另一个位置完整的生成该对象,也就是反序列化Deserialize。应用最多的场景可能就是将对象存储到磁盘,或者更多的是网络传输中。更简单一点,把对象看成是你网购的手机,商家给你打包后,经过物流公司再运输到你手里,你把包装拆开,得到一个完好无损的手机。商家打包过程叫做序列化,你拆包叫做反序列化,就这么简单。我们经常打交道的,就是调用HSF接口后的返回的对象,如果不进行序列化,肯定会出问题。

2. 实现起来也很简单,只要实现Serializeable接口就OK了。

下面例子讲一个对象存储到本地磁盘,这是序列化过程;再将该对象从磁盘中读出来,这就是反序列化;

先序列化对象 p到本地磁盘cat.txt中,再将其反序列化输出;

package com.taobao.mm.august;import java.io.FileOutputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class Cat implements Serializable {private static final long serialVersionUID = 4137418318779320231L;//引用类型    private String name;    //基本类型    private int age;//没有提供无参的构造函数       public Cat(String name,int age){    System.out.print("带参数构造函数!");    this.name = name;    this.age = 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;}public static void main(String[] args)  {ObjectOutputStream output = null;try{output = new ObjectOutputStream(new FileOutputStream("cat.txt"));Cat p = new Cat("馄饨",1);//关键的一步 将对象写入 cat.txtoutput.writeObject(p);//关闭输出流output.close();}catch (Exception e) {System.out.print(e);}}}
此时我们将Cat 对象p 存入本地磁盘上的cat.txt中。cat.txt文件我们一会再说,先看一下反序列化的代码。

反序列化代码:

package com.taobao.mm.august;import java.io.FileInputStream;import java.io.ObjectInputStream;/** * 用于反序列化 将cat.txt中的对象还原 */public class GetCat {public static void main(String[] args) {ObjectInputStream input = null;try{input = new ObjectInputStream(new FileInputStream("cat.txt"));//readObject返回值是Object 需要强制转换Cat p =  (Cat) input.readObject();System.out.println(p.getName());//System.out.println(p.getAge());////关闭输出流input.close();}catch (Exception e) {System.out.print(e);}}}
输出毫无疑问,是馄饨和1。

注意,反序列化时没有输出构造器中“带参数的构造函数!”这句话,这表明反序列化时并没有调用构造函数!

关于序列化,有几点是值得注意的:

1. 如果我们向文件中输出了多个序列化的对象,反序列化时要按照之前顺序读取;

2. 如果一个可序列化类有多个父类,则该类所有父类要么是可序列化(实现了Serializable接口),要么有无参的构造函数;

3. 和类的初始化类似,反序列化的时候,会先将所有父类初始化,首先考虑使用反序列化机制,如果不可序列化(未实现Serializable接口),则调用默认构造函数,否则抛异常

4. 一个对象想要实现序列化,其中的引用成员必须也实现序列化,如Cat 中String name 我们看String类定义就可以发现,String是实现了Serializable接口的。

5. 当某个对象被多个其他对象引用时,例如类B中引用了A 对象a,类C中也引用了a,那么当着三个文件都被序列化时,每个对象仅被实例化一次,不会出现多个a对象!因为每个对象都被赋予一个唯一序列化编号,反序列化时,会首先判断该对象是否被反序列化,如果已经被实例化了,那么接下来再对该对象的反序列化,只会付给一个序列化编号。这就保证同一个对象不会被多次生成。

6. 当一个对象A a;被多次序列化时,只有第一次序列化才会把java对象a转化成字节序列并输出,即使后面对该对象a进行修改,也无法再次生成字节序列,程序只是输出第一次的序列化编号而已。

7. private static final long serialVersionUID = 4137418318779320231L;这个熟悉吧,相当于版本控制的标识,当类反序列化的时候,先检查一下本地该类class文件中的UID是不是和当前的相同,如果相同就可以进行反序列化了。


好 先写到这里吧。

对了,cat.txt还没研究呢,先把图贴出来,下次再研究一下。