1.1 未序列化类型子类进行序列化
1.1.1 序列化是什么
想知道这个问题的答案,就要先读序列化源码的第一段内容
一个类可序列化的开关,通过实现 java.io.Serializable 开启。如果一个类不实现这个接口就不能进行任何的序列化或者反序列化操作(IO之类的)。所有序列化类的子类型也是可以被序列化的。用于序列化的接口没有任何的属性或者方法,唯一的作用只是对在语义(semantic)上标识类是可序列化的。
整理一下关键信息:
1.1.2 父类未实现序列化接口,子类实现序列化接口会发生什么?
允许未序列化类的子类进行序列化,当它的父类型的属性权限是 public, protected 或者(如果是的话)包,子类型可以承担存取父类型的职责。 子类型可以承担职责当且仅当这个类继承的父类有一个无参构造来初始化话类数据。如果没有达成这个条件会产生错误。这个错误将在运行时被发现(be detected)。
整理一下关键信息:
我们来试下,如果父类未实现序列化接口,子类实现了,没有无参构造会发生什么:
public class A {private static final long serialVersionUID = 1L;
protected int b;
//显示下面这句就不会报错
// public A(){}
public A(int b){
this.b = b;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
@Override
public String toString() {
return "{b="+b+"}";
}
}public class B extends A implements Serializable {
private int c;
public B(int c){
super(0);
this.c = c;
}
@Override
public String toString() {
return "{b="+b+",c="+c+"}";
}
}import java.io.*;
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Main solution = new Main();
A a = new B(4);
a.setB(7);
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("E:/aa.txt")));
oo.writeObject(a);
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/aa.txt")));
A person = (A) ois.readObject();
System.out.println(person);
}
}
子类型可以承担职责当且仅当这个类继承的父类有一个无参构造来初始化类数据。
尊重科学,给类型A加上无参构造试试:
import com.dyy.jdk8.test.A;import java.io.*;
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Main solution = new Main();
A a = new A();
a.setB(7);
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("E:/aa.txt")));
oo.writeObject(a);
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/aa.txt")));
A person = (A) ois.readObject();
System.out.println(person);
}
}import java.io.Serializable;
public class A implements Serializable {
private static final long serialVersionUID = 988077679676L;
private int b;
public A(){}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
@Override
public String toString() {
return "{b="+b+"}";
}
}
OK,这一段搞定
在反序列化过程中,未序列化的类需要使用public或者protected级别的构造器进行初始化。没有参数的构造必须要有个对应可以序列化的子类。子类的属性在序列化的过程中将被保存在流中。
这一段也很好理解,如果未序列化的类构造不是 public 或者 protected 级别的,就无法在序列化过程中被调用,这一段可以和前一段放在一起理解:
如果子类序列化,父类不序列化,父类必须有public/protected 级别的无参构造。
1.1.3 未实现 Serializable 接口,进行流的输入输出
在遍历对象图的过程中,一个对象可能不支持序列化接口。
这种情况下会对没有序列化的类型抛出 NotSerializableException 异常,让我们看下:
试一下把这里改成A的对象。
出现这个异常。
1.1.4 小结
PS: 我不是一个高手,只是一个期望在枯燥的源码中找出点乐趣的普通人。英语很难,我的英语很差,参考百度翻译一段英语理解了很多次(其实有的部分,参考翻译还是看不太懂,就要不停的去想,去证实自己理解的对不对)。
如果理解的不正确,欢迎读者骂我,达者为师,我尊师重道,感谢您的指导与批评!
【转自:香港高防 http://www.558idc.com/stgf.html转载请说明出处】