Java当中的序列化,其主要的作用是将类的实例进行无损传输,或者说就是通过Java的序列化机制,Java类的实例可以通过Object流来传输和重新获取,而不会损坏类的实例。
首先,我们看看什么样的类是序列化类,
1.A类自身实现了Serializable接口的类;
2.A类自身没有实现Serializable接口,但其父类实现了Serializable接口的类;
以上两种,我们认为是类A是序列化类。
在SCJP考试当中就有一道关于序列化的题目:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Food {
Food() {
System.out.print("1");
}
}
class Fruit extends Food implements Serializable {
Fruit() {
System.out.print("2");
}
}
public class Banana2 extends Fruit {
int size = 42;
public static void main(String[] args) {
Banana2 b = new Banana2();
b.serializeBanana2(b); // assume correct serialization
b = b.deserializeBanana2(b); // assume correct
System.out.println(" restored " + b.size + " ");
}
// more Banana2 methods
public static void serializeBanana2(Banana2 b) {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("c:/a.txt"));
out.writeObject(b);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Banana2 deserializeBanana2(Banana2 b) {
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("c:/a.txt"));
return (Banana2) in.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
这道题的输出结果是:121 restored 42
从运行结果来看:前连个数字12是显而易见的,在new Banana2()的时候执行的,但是第三个1就不好理解了,其实,如果从多态的角度考虑,也不难理解,因为反序列化是要得到原类的实例,而这就需要在反序列化之前就得声明一个原始类或者原始类的父类的一个实例,在从Java多态的机制考虑,通过父类(基类)声明就容易理解了。
当然,这样对父类也有相应的要求,如果类A实现了序列化接口,而A的父类没有实现序列化接口,那么,在反序列化A的实例的时候,会首先执行一下A的父类的无参构造,因此这就要求:A的父类必须具备一个无参的构造函数,否则报错。如果父类也实现了序列化接口,那么在反序列化的时候,父类构造不会被执行。