现在的位置: 首页 > 综合 > 正文

Serializable可序列化接口

2016年12月14日 ⁄ 综合 ⁄ 共 2143字 ⁄ 字号 评论关闭

在Java中,我们可以用ObjectInputStream类和ObjectOutputStream类来实现对象的输入和输出,但是并非每一个对象都可以写到输入流中,我们把可以写入输入流中的对象称之为可序列化的,也就是Serializable的。在Java中,为了标识一个对象可以写入输出流,该对象的类必需实现Serializable接口,每个可序列化的对象都是该接口的一个实例。

如上所说,Serializable接口只是个标识,其内部并没有方法:

public interface Serializable {
}

实现该接口即可启动Java的序列化机制,自动完成存储对象和数组的过程。Java提供一个内在机制自动完成写对象的过程,这个过程称为对象序列化,它是在ObjectOutputStream中实现的;反过来呢,读取对象的过程称作对象反序列化,它是在ObjectInputStream中实现的。

考虑如下工程:

项目中我们有三个类,其中ClassA是个空类,仅仅实现了Serializable接口:

package com.aigestudio.test;

import java.io.Serializable;

public class ClassA implements Serializable {

}

而SerializableClass类中我们定义了如下几个字段:

package com.aigestudio.test;

import java.io.Serializable;

public class SerializableClass implements Serializable {
	private String strA;
	private int intA;
	private boolean booA;
	private ClassA classA = new ClassA();
}

其中,我们声明并实例化了ClassA类的一个实例对象,在Test中我们将SerializableClass的一个实例对象写入文本:

package com.aigestudio.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Test {
	public static void main(String[] args) throws IOException {
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("H:\\test.dat"));
		oos.writeObject(new SerializableClass());
		oos.close();
	}
}

运行后我们可以看到在文本中已经写入了二进制数据:


当试图往输出流中写入SerializableClass的对象时,Java会先检测SerializableClass对象中的所有对象是否都是可序列化的(我们代码中的classA对象),如果发现有不能序列化的对象,则会报出NotSerializableException异常。比如我将上面ClassA改为如下:

package com.aigestudio.test;

public class ClassA {

}

去掉了Serializable接口的实现,运行程序即会报出异常:

因为我们在Test中试图输出SerializableClass对象时发现其中有不可序列化的ClassA对象。
如果我们想输出SerializableClass对象而不需要管ClassA对象且不想让ClassA对象实现Serializable接口,这时该怎么办呢?很简单,我们只需在声明时给ClassA对象加上transient关键字即可,这时Java在对SerializableClass对象进行编码时就会忽略掉ClassA对象:

package com.aigestudio.test;

import java.io.Serializable;

public class SerializableClass implements Serializable {
	private String strA;
	private int intA;
	private boolean booA;
	private <span style="color:#990000;"><strong>transient</strong></span> ClassA classA = new ClassA();
}

编译运行:

 = =虽然咱们看不懂,但是数据已变对吧、、、呵呵呵呵呵呵呵……

除了transient关键字外,静态变量也会被忽略写入输出流,具体就不演示了~有兴趣自己可以去试试……

当存储一个可序列化对象时,会对该对象的类进行编码。编码包括类名、类的签名、对象实例变量的值以及从初始对象引用的任何其他对象的闭包,但是不存储对象静态变量的值。

当第一次写入一个对象时,会为该对象创建一个序列号,Java虚拟机将对象的所有内容和序列号一起写入对象流,以后每次存储如果再写入相同的对象就只存储序列号。读取这些对象时,它们的引用都相同,因为在内存中实际上存储的只是一个对象。

抱歉!评论已关闭.