鸟菜基础篇_2012_8_26序列化

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

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.txt
			output.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还没研究呢,先把图贴出来,下次再研究一下。



你可能感兴趣的:(鸟菜基础篇_2012_8_26序列化)