• 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

  • 相关阅读:
    异常处理
    组合,封装
    自我介绍
    27python更多实例
    28python类代码编写细节
    29python运算符重载
    30python 类的设计
    31python类的高级主题
    32python异常基础
    33python异常编码细节
  • 原文地址:https://www.cnblogs.com/wanghq1994/p/12145117.html
Copyright © 2020-2023  润新知