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

java序列化(二)的更多相关文章

  1. Java 序列化和反序列化(二)Serializable 源码分析 - 1

    目录 Java 序列化和反序列化(二)Serializable 源码分析 - 1 1. Java 序列化接口 2. ObjectOutputStream 源码分析 2.1 ObjectOutputSt ...

  2. 理解Java对象序列化(二)

    关于Java序列化的文章早已是汗牛充栋了,本文是对我个人过往学习,理解及应用Java序列化的一个总结.此文内容涉及Java序列化的基本原理,以及多种方法对序列化形式进行定制.在撰写本文时,既参考了Th ...

  3. Java序列化与反序列化

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...

  4. [转] Java序列化与反序列化

    原文地址:http://blog.csdn.net/wangloveall/article/details/7992448 Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java ...

  5. Java序列化的几种方式以及序列化的作用

    Java序列化的几种方式以及序列化的作用 本文着重讲解一下Java序列化的相关内容. 如果对Java序列化感兴趣的同学可以研究一下. 一.Java序列化的作用    有的时候我们想要把一个Java对象 ...

  6. Java学习笔记(十七)——java序列化

    [前面的话] 做项目总是要用到很多东西,遇到一个新的知识,并不是这个知识出来的时间短,而是对于自己来说是新的,所以就需要自己去学习,希望今后可以提高学习的效率. 这篇文章是关于Java 序列化的,选择 ...

  7. java基础知识回顾之javaIO类--java序列化和反序列化

    /** *  * 一:理解序列化反序列化及其应用 * 序列化:把堆内存的对象转化成字节流的过程. * 反序列化:把字节流序列恢复重构成对象的过程. * 对象的序列化的用途:1.把对象的字节序列持久化, ...

  8. Java序列化接口的作用总结

    一个对象有对应的一些属性,把这个对象保存在硬盘上的过程叫做”持久化”. 把堆内存中的对象的生命周期延长,存入硬盘,做持久化操作.当下次再需要这个对象的时候,我们不用new了,直接从硬盘中读取就可以了. ...

  9. Java序列化技术

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化? Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象 ...

  10. java 序列化 serialVersionUID 的作用 和 两种添加方式

    serialVersionUID适用于Java的序列化机制.简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的 ...

随机推荐

  1. oracle自动选择索引

    如果表中有两个以上(包括两个)索引,其中有一个唯一性索引,而其他是非唯一性. 在这种情况下,ORACLE将使用唯一性索引而完全忽略非唯一性索引. 举例: SELECT ENAME FROM EMP W ...

  2. yii框架不输出头文件和尾文件

    控制器: public function actionCat(){ return $this->renderPartial('cat');} 在进行页面输出渲染的时候. 1.render 输出父 ...

  3. servicemix 实例 -- 参考open source ESBs in action这本书

    1. 项目结构 2. bean服务处理单元 1)Person类 package esb.chapter3; import java.io.StringWriter; import javax.xml. ...

  4. 蝶式套利(butterfly spread)

    多头蝶式套利.预期市场价格趋于稳定,希望在这个价格区间内能获利,可选用多头蝶式套利,以较低的议定价格买进一个看涨期权,又以较高的议定价格买进一个看涨期权,同时又以介于上述2个议定价格之间的中等的议定价 ...

  5. 初次使用pycharm 的interpreter option为空解决办法。

    第一步:进入Setting. 第二步:进入Project中的Project Interpreter.选择添加即可.

  6. java 内省 了解JavaBean

    JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则. 如果要在两个模块之间传递多个信息,可以将这些信息封装到一个Jav ...

  7. dotnet 使用 GC.GetAllocatedBytesForCurrentThread 获取当前线程分配过的内存大小

    在 dotnet framework 4.8 的时候支持调用 GC.GetAllocatedBytesForCurrentThread 获取当前线程分配过的内存大小 创建一个简单的控制台程序,在调用 ...

  8. tomcat下的work目录和temp目录

    1. tomcat下的work目录 1    用tomcat作web服务器的时候,部署的程序在webApps下,这些程序都是编译后的程序(发布到tomcat的项目里含的类,会被编译成.class后才发 ...

  9. win10 uwp 解决 SerialDevice.FromIdAsync 返回空

    调用 SerialDevice.FromIdAsync 可能返回空,因为没有设置 package.appmanifest 可以使用端口 打开 package.appmanifest 文件添加下面代码 ...

  10. error:cannot load file (code:5555h);bootauto.ini

    最近发现有的网友在使用Ghost XP盘安装系统的时候,选择一键ghost到C盘出现下面的错误: error:cannot load file (code:5555h);bootauto.ini(或b ...