5)序列化中,子类和父类构造函数的调用问题
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用
一个类实现了序列化接口,那么其子类都可以进行序列化
这个地方我们要去体悟一下,还不是特别的明白的。
一个类实现了序列化接口,子类就一定能序列化
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类构造函数会被调用,如果实现了序列化接口,反序列化时该父类可以直接从序列化时指定的用于存储的文件里读取数据
序列化和反序列化操作:对子类和父类构造函数调用问题:
如图:总结:
1、当将一个父类没有实现序列化的对象son使用ObjectOutputStream流写到本地文件中时,没有能将该对象中属于父类的部分写入到文件,因为ObjectOutputStream流不能将一个没有实现序列化的类的对象写入文件中。当将本地文件中保存的son对象通过ObjectInputStream流反序列化到程序中,由于缺少属于父类的部分信息,则需要再次调用父类的构造器来完成初始化
一个类实现了序列化接口,那么其子类都可以进行序列化
1、一个类实现了序列化接口,那么其子类都可以进行序列化。
2、对子类对象进行反序列化操作时,
如果其父类没有实现序列化接口
那么其父类构造函数会被调用
对子类对象进行序列化操作时,父类的构造函数会被调用;对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用。
1、无论子、父类是否实现序列化接口,创建子类对象时都会递归调用父、子类构造函数
2、没有实现序列化接口的父类们不会被序列化到文件
3、在反序列化操作时,由于没有实现序列化接口的父类们没有被序列化到文件中,所以在生成其子对象时jvm自动调用了父类们的无参构造方法
当父类已经实现 Serializable 接口时,子类不需要重复实现该接口。
注意:若其更高层的某一父类没有实现该接口,则在反序列化时,会显示调用其父类的构造函数。(已实现该接口的类在反序列化是不会显示调用其构造函数)
序列化中,子类和父类构造函数的调用问题
一个类实现了序列化接口,那么其子类都可以进行序列化
//序列化递归调用了父类的构造函数
//对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用
当父类实现序列化接口时,继承此父类的子类不必再进行序列接口的实现。
但当父类实现序列化接口时,在主函数内序列化子类并反序列化输出时,父类的构造函数不会被调用。
对子类对象急性反序列化操作时,如果其匪类没有实现序列化接口,那么其父类的构造函数会被显式调用。
但在序列化的过程当中,会对其全部的父类(包括间接的父类也调用构造函数)
序列化与反序列化的操作:
ObjectOutputStream oss = new ObjectOutputStream( new FileOutputStream(path)) 这个是序列过程,在oss当中需要套用到字节流
oss.writeObject(new Foo()), 将对象序列化以后保存path当中。
ObjectInputStream ois = new ObjectInputStream( new FileInputStream(path))这个是反序列过程,在ois当中需要套用到字节流
Foo foo = ois.readObject()
实现序列化接口的类以及子类在进行反序列化操作都不会显示调用构造函数,未实现序列化接口的类会显示调用其构造函数
对子类对象进行反序列化操作时,
如果其父类没有实现序列化接口,
那么其父类的构造函数会被调用
父类没有实现序列化接口,那么在反序列化时就会调用父类的构造函数。
序列化和反序列化可以同时操作,比如读取文件1里的内容后,再把该文件1的内容拷贝(写入)到文件2里去,需要同时操作输入和输出,输出表示序列化,输入表示反序列化。
序列化中父类构造函数问题
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用。
public class ObjectSeriaDemo2 {
public static void main(String[] args) throws Exception{
/*ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("demo/obj1.dat"));
Foo2 foo2 = new Foo2();
oos.writeObject(foo2);
oos.flush();
oos.close();*/
//反序列化是否递归调用父类的构造函数
/*ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("demo/obj1.dat"));
Foo2 foo2 = (Foo2)ois.readObject();
System.out.println(foo2);
ois.close();*/
/*ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("demo/obj1.dat"));
Bar2 bar2 = new Bar2();
oos.writeObject(bar2);
oos.flush();
oos.close();*/
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("demo/obj1.dat"));
Bar2 bar2 = (Bar2)ois.readObject();
System.out.println(bar2);
ois.close();
/*
* 对子类对象进行反序列化操作时,
* 如果其父类没有实现序列化接口
* 那么其父类的构造函数会被调用
*/
}
}
/*
* 一个类实现了序列化接口,那么其子类都可以进行序列化
*/
class Foo implements Serializable{
public Foo(){
System.out.println("foo...");
}
}
class Foo1 extends Foo{
public Foo1(){
System.out.println("foo1...");
}
}
class Foo2 extends Foo1{
public Foo2(){
System.out.println("foo2...");
}
}
class Bar{
public Bar(){
System.out.println("bar");
}
}
class Bar1 extends Bar{
public Bar1(){
System.out.println("bar1..");
}
}
class Bar2 extends Bar1 implements Serializable{
public Bar2(){
System.out.println("bar2...");
}
}
5)序列化中 子类和父类构造函数的调用问题
父类实现了序列化接口:
其子类都可以进行序列化
序列化:把关于父类的信息也写入文件,因为用到了子类,所以会递归调用父类的构造方法
反序列化:因为序列化时已经把关于父类的信息写入文件,所以读取的时候就不再调用父类的构造函数初始化父类的信息。
子类实现了序列化接口:
序列化:因为用到了子类,所以会递归调用父类的构造方法,但是不会把关于父类的信息写入文件
反序列化:读取到的信数据因为没有父类的信息,所以要重新调用父类的构造方法来初始化信息。
代码:
public class ObjectSeriaDemo2 {
public static void main(String[] args) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("demo/obj1.dat"));
f1 f1=new f1();
oos.writeObject(f1);
oos.flush();
oos.close();
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("demo/obj1.dat"));
f1 f2=(f1)ois.readObject();
System.out.println(f2);
}
}
class f {
public f() {
System.out.println("f");
}
}
class f1 extends f implements Serializable{
public f1() {
System.out.println("f1");
}
}
结果:
f
f1
f
com.imooc.io.f1@776ec8df
对类的对象反序列化时,如果其父类没有实现序列化接口,那么父类的构造方法会被调用
父类实现了序列化接口,子类就不用再实现序列化接口,子类可以直接序列化
4
3
2
1
序列化中父子类的构造函数的问题:<br>
1:一个类实现了序列化接口,那么其子类都可以进行序列化<br>
2:序列化的时候,使用子类创建对象的时候会递归调用父类的构造函数——JAVA是单继承的语言,要先有父再有子
3:反序列化的时候,对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被递归调用——直接父类和间接父类都是如此的,反之,如果父类实现了序列化的接口,那么子类继承它的属性和方法就可以直接反序列化,就不会调用父类的构造函数了。