上一篇我们简单的了解了java的序列化方法。可以想一下,如果有两个类,如果父类实现了序列化,子类没有实现序列化,子类在进行对象序列化读写时,父类和子类均被实现序列化。如果其中父类没有实现序列化,子类实现了序列化,那么序列化和反序列化会发生什么情况呢?大胆猜测一下,父类没有经过序列化,所以他的属性不会被保留下来,在反序列化时应该没值。下面分两种情况验证一下。
第一种是父类无空参构造函数
package serializable.testone; /** * @Description: 未实现序列化的父类 * @Author: haoqiangwang3 * @CreateDate: 2020/1/3 */ public class Biology { public String type; private int num; /** * 父类构造函数 * @param type * @param num */ public Biology(String type, int num){ this.type = type; this.num = num; } public String getType() { return type; } public void setType(String type) { this.type = type; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } }
子类继承父类,并实现了序列化
package serializable.testone; import java.io.Serializable; /** * @Description: 实现序列化的子类 * @Author: haoqiangwang3 * @CreateDate: 2020/1/3 */ public class PeoPle extends Biology implements Serializable { public String name; protected String gender; private int age; /** * 子类构造函数 * @param type * @param num * @param name * @param gender * @param age */ public PeoPle(String type, int num, String name, String gender, int age){ super(type,num); this.name = name; this.gender = gender; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
最后测试一下结果
package serializable.testone; import java.io.*; /** * @Description: 测试类 * @Author: haoqiangwang3 * @CreateDate: 2020/1/3 */ public class TestOne { public static void main(String[] args) throws IOException, ClassNotFoundException { PeoPle peoPle = new PeoPle("human",10000,"张三","男",25); //序列化,写到文件中 FileOutputStream fos = new FileOutputStream("test.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(peoPle); oos.flush(); oos.close(); System.out.println("序列化成功..."); //反序列化 FileInputStream fis = new FileInputStream("test.txt"); ObjectInputStream ois = new ObjectInputStream(fis); PeoPle p = (PeoPle)ois.readObject(); System.out.println("p.getType() = " + p.getType()); System.out.println("p.getNum() = " + p.getNum()); System.out.println("p.getName() = " + p.getName()); System.out.println("p.getGender() = " + p.getGender()); System.out.println("p.getAge() = " + p.getAge()); } }
运行结果如下:
序列化成功... Exception in thread "main" java.io.InvalidClassException: serializable.testone.PeoPle; no valid constructor at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169) at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:874) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2043) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) at serializable.testone.TestOne.main(TestOne.java:26)
可以发现,序列化成功了,但是反序列化的时候发生了异常。
第二种,父类含有无参构造函数。
package serializable.testtwo; public class Person { public String name; public String gender; public int age; float height; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public float getHeight() { return height; } public void setHeight(float height) { this.height = height; } }
子类如下
package serializable.testtwo; import java.io.Serializable; public class Male extends Person implements Serializable { private static final long serialVersionUID = 1L; public boolean beard; protected String weight; public boolean haveBeard(int age){ boolean flag = false; if(age >= 18){ flag = true; } return flag; } public boolean isBeard() { return beard; } public void setBeard(boolean beard) { this.beard = beard; } public String getWeight() { return weight; } public void setWeight(String weight) { this.weight = weight; } }
测试类:
package serializable.testtwo; import java.io.*; public class TestTwo { public static void main(String[] args) throws IOException, ClassNotFoundException { /**Male继承父类Person,自身实现序列化接口,其父类Person没有实现序列化接口*/ FileOutputStream fos = new FileOutputStream("male.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); Male male = new Male(); /** 父类属性赋值 */ male.setName("张三"); male.setGender("男"); male.setAge(25); male.setHeight(175); /**其自身属性赋值*/ male.setBeard(true); male.setWeight("150"); //序列化 oos.writeObject(male); oos.flush(); oos.close(); //反序列化 FileInputStream fis = new FileInputStream("male.txt"); ObjectInputStream ois = new ObjectInputStream(fis); Male ml = (Male) ois.readObject(); //结果打印 System.out.println("ml.getName() = " + ml.getName()); System.out.println("ml.getGender() = " + ml.getGender()); System.out.println("ml.getHeight() = " + ml.getHeight()); System.out.println("ml.getAge() = " + ml.getAge()); System.out.println("ml.isBeard() = " + ml.isBeard()); System.out.println("ml.getWeight() = " + ml.getWeight()); } }
运行结果如下
ml.getName() = null ml.getGender() = null ml.getHeight() = 0.0 ml.getAge() = 0 ml.isBeard() = true ml.getWeight() = 150
可以发现,序列化和反序列都没有报错,但是反序列化之后父类的属性值都没有。这也验证了我们之前的猜想。
总结一下:
1、非序列化的父类,其子类实现序列化时承担保存和恢复父类public、protected、package等子类可访问到子类的字段;
2、非序列化的父类,其子类进行序列化时,父类需要有用public或者protected修饰的空参构造函数;
3、若无空参构造函数的父类,其子类在运行序列化时将正常进行,但反序列化时会发生错误,并抛出异常。但父类有空参构造函数,子类完成序列化,父类属性却没有参与到序列化中。
其中还有其他稍微复杂的应用,在此就不多说了,详细可以看下此文章:https://mp.weixin.qq.com/s/Ta0vhFEZL2wGk2x1ES7HHg