(1)java序列化--java.io.Serializable接口解析

(PS:本文为做者原著,如需转载,请注明出处-_^)      java

    使用java以来,序列化随处可见,至于为何要用序列化、序列化能解决什么问题,做为一个普通的码农,通常不怎么会去深刻研究,因为最近在看mina和公司内部涉及到nio框架的一些源码,里面涉及到hession、java这两种序列化,至于hession序列化为何会诞生以及在apache项目中使用如此普遍,以及java自己序列化存在哪些缺陷,甚是不解,为了解答上面抛出来的疑惑,以及进一步了解java的序列化机制,这里开个小头,从java的序列化接口Serializable开始提及apache

jdk包里的Serializable接口的注释主要说明了如下几点:数组

1.类经过实现Serializable接口来启用序列化,不然该类的任何状态将没法被序列化,同时也没法用于反序列化框架

2.若继承的父类没有实现Serializable接口,可是又想让子类可序列化,有三个注意事项:jvm

    a).子类实现Serializable接口测试

    b).子类必须有可访问的无参构造方法,用于保存和恢复父类的public或protected或同包下的package字段的状态,不然在序列化或反序列化时会抛出RuntimeException异常spa

    c).对于序列化后的子类,在进行反序列化时,理论上没法初始化父类中private(不可访问)对象变量的状态或值
操作系统

3.在对可序列化类中的属性进行序列化时,若是遇到不可序列化的对象变量,此时会针对不可序列化的类抛出NotSerializableException异常code

4.对于可序列化的非数组类,强烈建议显示声明static型、long型、final型serialVersionUID字段用于标识当前序列化类的版本号,不然在跨操做系统、跨编译器之间进行序列化和反序列化时容易出现InvalidClassException异常orm

5.对于可序列化类中的static、transient对象变量,在序列化时没法保存其状态或值,static对象变量在反序列化时取得的值为当前jvm中对应类中对应static变量的值,而transient(瞬态)关键字则通常用于标识那些在序列化时不须要传递的状态变量

 简单的测试代码:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 序列化测试
 * 
 * @author sume
 * 
 */
public class SerializableImpl implements Serializable {

	private static final long serialVersionUID = -6433786313435044319L;

	static String staticVal = "static1";
	transient String transientVal = "transient1";
	String val = "val1";

	/**
	 * main
	 */
	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		// 序列化
		SerializableImpl sila1 = new SerializableImpl();
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("Serializable.txt"));
		objectOutputStream.writeObject(sila1);
		objectOutputStream.close();

		// 反序列化
		SerializableImpl.staticVal = "static2";
		ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("Serializable.txt"));
		SerializableImpl sila2 = (SerializableImpl) objectInputStream.readObject();
		objectInputStream.close();

		// 比较各个属性的值
		System.out.println(sila2.staticVal);
		System.out.println(sila2.transientVal);
		System.out.println(sila2.val);
	}
}
输出结果:

static2
null
val1

从输出结果能够看出:

1.反序列化后类中static型变量staticVal的值为当前jvm中对应static变量的值,为:static2,而不是序列化时的值:static1

2.transient关键字标识的变量的状态并无在序列化中被保存,所以反序列化后

transientVal变量的值为null

3.第三个为常见的对象状态在序列化和反序列化过程当中的传递

简单印证了前面所说的几点内容

另外:对于在序列化和反序列化过程当中须要对类进行特殊处理或须要指定替代对象的操做,

本文没有涉及到,会在后面进一步讨论时给出

相关文章
相关标签/搜索