java序列化(二)

上一篇我们简单的了解了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

原文地址:https://www.cnblogs.com/wanghq1994/p/12145117.html