思维导图
Java内部用于序列化与反序列化的接口有两个,一个是Serializable ,另一个时Externalizable,这两者的区别是如果类实现了Serializable接口,序列化时就会直接写入二进制文件Externalizable继承自Serializable接口,实现了Externalizable接口的类在序列化时必须规定那些要序列化,那些不需要序列化。而且,在反序列化时,会调用类的默认的构造方法,也就是说,如果一些数据没在默认构造方法中初始化,又没被专门写入的化,这些数据就不会被反序列化。
序列化需要使用继承自InputStream和oOutputStream的ObjectInputStream,ObjectOutputStream,这两个类是修饰流。下面是个简单的小例子。,将一个对象序列化后又进行反序列化,其中涉及到了对象含有对象引用的情况,也说明了对象网的序列化会不会重复。
package IOdemo;
import java.io.*;
public class SerializableDemo {
public static void main(String[] args){
try {
//文件对象
File file = new File("e:/object");
//输出流
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
//写入对象
TestObject to1 = new TestObject("to1");
TestObject to2 = new TestObject("to2");
//测试对象网是否能被写入
//若果两个对象拥有同一个对象的引用,这个引用对象不会被重复创建
to2.setObject(to1);
oos.writeObject(to2);
//输出流
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
//读取对象时,保证虚拟机找到class文件,不然报ClassNotFoundException异常
TestObject to = (TestObject)ois.readObject();
System.out.println(to.name);
System.out.println(to.object.name);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
//测试的对象
class TestObject implements Serializable{
String name;
//测试对象网是否能被序列化
TestObject object;
TestObject(String name){
this.name = name;
}
public void setObject(TestObject object) {
this.object = object;
}
}
上面的小例子是默认的序列化情况,也有一些特殊的情况需要处理,比如,不想一个字段被序列化和反序列化-----使用transient关键字,transient关键字只适用于Serializable接口。怎么自定义序列化方法,又怎么在自定义的序列化方法中调用默认的序列化方法,静态字段如何序列化。 看下面的例子。
//测试的对象
class TestObject implements Serializable{
//静态字段不会被自动序列化
static String name;
transient String nothing;
//静态对象不会被默认序列化,所以,必须调用特殊的方法
//静态对象的序列化方法
public static void serializeStaticState(ObjectOutputStream oos) throws IOException{
oos.writeUTF(name);
}
//静态对象的反序列化方法
public static void deserializeStaticState(ObjectInputStream ois) throws IOException{
name = ois.readUTF();
}
//可以自定义序列化方法
private void writeObject(ObjectOutputStream oos) throws IOException{
//也可在在这个方法中调用默认的序列化方法
oos.defaultWriteObject();
//然后进行需要自定义的序列化
}
//可以自定义反序列化方法
private void readObject(ObjectInputStream ois) throws IOException,ClassNotFoundException{
//也可在在这个方法中调用默认的反序列化方法
ois.defaultReadObject();
//然后进行需要自定义的反序列化
}
}
以上是实现Serializable接口的序列化方法,可以自动的序列化,也可以手动的序列化,而实现Externalizable接口则必须进行手动的序列化。看下面的例子。
//测试的对象2
class TestObject2 implements Externalizable{
String name;
//Externalizable在反序列化时,只会调用默认的构造器进行初始化,也就是说,如果
//构造函数里没有赋值,有没有在方法里写入和读取,那么字段的值反序列化后会是0或者null,false
public TestObject2(){
}
//Externalizable不会自动序列化对象,必须手动序列化
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name);
}
//Externalizable不会自动反序列化对象,必须手动反序列化
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = in.readUTF();
}
}
最后,序列化技术可以用于网络远程调用和bean的创建。