提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、Serializable接口的作用
  • 二、Serializable接口的使用
    • 1.引入库
    • 2.读入数据
    • 3.serialVersionUID
    • 4.静态变量序列化
    • 5.transient关键字
    • 序列化中的继承问题

前言

开发中遇到过很多实现Serializable接口的类,也会很迷惑这个接口不提供任何变量和方法,最近有时间就来深挖一下Serializable吧


一、Serializable接口的作用

Serializable接口的作用是实现序列化
序列化:对象的寿命通常随着生成该对象的程序的终止而终止,有时候需要把在内存中的各种对象的状态(也就是实例变量,不是方法)保存下来,并且可以在需要时再将对象恢复。虽然你可以用你自己的各种各样的方法来保存对象的状态,但是Java给你提供一种应该比你自己的好的保存对象状态的机制,那就是序列化

系列化的用途

  • 需要把的内存中的对象状态保存到一个文件中或者数据库中时候
  • 需要把对象通过网络进行传播的时候

二、Serializable接口的使用

1.引入库

2.读入数据

代码如下(示例):

public class SerializableTest {public static void main(String[] args)  throws Exception{System.out.println("--------");Student student = new Student("xiaoming",18,"0207");File file = new File("src/Resource/file11.txt");System.out.println("--------");//写入对象FileOutputStream fos = null;ObjectOutputStream oos = null;fos = new FileOutputStream(file);oos = new ObjectOutputStream(fos);Student person = new Student("tom", 22,"0702");System.out.println(person);oos.writeObject(person);oos.close();fos.close();//读出对象FileInputStream fis = null;fis = new FileInputStream(file);ObjectInputStream ois = null;ois = new ObjectInputStream(fis);Student person_read = null;person_read = (Student)ois.readObject();System.out.println(person_read);ois.close();fis.close();}
}@Data
@AllArgsConstructor
@ToString
class Student implements Serializable {// 如果将 implements Serializable 去掉,将无法实现序列化 此时运行程序,报java.io.NotSerializableException异常private static final long serialVersionUID = 1L;private String name;private int age;private String classname;
}

控制台输出

Student(name=tom, age=22, classname=0702) Student(name=tom, age=22, classname=0702)


3.serialVersionUID

序列化 ID 提供了两种生成策略

  • 一个是固定的 1L
  • 一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段

上面程序中,输出对象和读入对象使用的是同一个Student 类。 如果是通过网络传输的话,如果Student
类的serialVersionUID不一致,那么反序列化就不能正常进行。例如在客户端A中Student类的serialVersionUID=1L,而在客户端B中Student 类的serialVersionUID=2L
那么就不能重构这个Student 对象,报java.io.InvalidClassException异常

注:假设客户端A与客户端B中有一个serialVersionUID相同但字段不完全相同的Student类,进行反序列化时,仅会保留当前执行反序列化这一端的Student类的字段,另一端的不同字段将会被遗漏

4.静态变量序列化

串行化只能保存对象的非静态成员交量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符都不能保存。

如果把Person类中的name定义为static类型的话,试图重构,就不能得到原来的值,只能得到null。说明对静态成员变量值是不保存的。这其实比较容易理解,序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量

5.transient关键字

经常在实现了 Serializable接口的类中能看见transient关键字。这个关键字并不常见。 transient关键字的作用是:阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。

当某些变量不想被序列化,同是又不适合使用static关键字声明,那么此时就需要用transient关键字来声明该变量
例如:如果将classname 属性设置为transient private transient String classname; 则输出为Student(name=tom, age=22, classname=null)

序列化中的继承问题

  • 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口。
  • 一个子类实现了 Serializable 接口,它的父类都没有实现 Serializable 接口,要想将父类对象也序列化,就需要让父类也实现Serializable 接口

将代码修改为如下:

  Student person = new Student("tom", 22,"0702", (float) 5.20);@Data
@ToString
class Student extends Person implements Serializable {/***   如果将 implements Serializable 去掉,将无法实现序列化 此时运行程序,报java.io.NotSerializableException异常*/private static final long serialVersionUID = 1L;private String name;private int age;private String classname;private float birth;public Student(String name,int age,String classname, float birth){super(name,age,birth);this.classname = classname;}
}
@Data
@AllArgsConstructor
@ToString
class Person{private String name;private int age;private float birth;public Person(){}
// 控制台打印
Student(name=null, age=0, classname=0702, birth=0.0)
Student(name=null, age=0, classname=0702, birth=0.0)

如果父类不实现 Serializable接口的话,就需要有默认的无参的构造函数。这是因为一个 Java 对象的构造必须先有父对象,才有子对象,反序列化也不例外。在反序列化时,为了构造父对象,只能调用父类的无参构造函数作为默认的父对象。因此当我们取父对象的变量值时,它的值是调用父类无参构造函数后的值。在这种情况下,在序列化时根据需要在父类无参构造函数中对变量进行初始化,否则的话,父类变量值都是默认声明的值,如 int 型的默认是 0,string 型的默认是 null

Serializable接口分析相关推荐

  1. Serializable 都这么牛逼了,Parcelable 还要你何用?

    一些闲聊 距离上一篇文章似乎又是很久了,看起来也没有很多反馈,催更就更不用说了.哈哈,放弃了. 话说最近公司在招聘一批至少 5 年开发经验的 Android 开发工程师,我也是忙开了花,激动得不行呀. ...

  2. Parcelable与Serializable的比较

    Parcel: Android中的序列化方式,可用于跨进程传输 Parcelable 进程间 如:想从一个第三方app拿进程回来 Serializable 进程内

  3. Java开发规范,不要新建一个类就实现Serializable接口

    个人网站:http://xiaocaoshare.com/ 作为一名java开发者,细节决定技术的高度和深度 一个java类什么时候需要实现Serializable接口 1.什么是Serializab ...

  4. Spark Troubleshooting - Task not serializable问题分析

    本文首发于 www.yidooo.net/2018/08/19/- 转载请注明出处 问题描述 出现"org.apache.spark.SparkException: Task not ser ...

  5. javax顶层接口分析

    1.Servlet接口分析 此接口是Servlet的最顶层接口,其中定义了Servlet生命周期相关的方法,所有Servlet都必须实现.此接口中的方法有以下几个: public void init( ...

  6. Java Lock接口分析之ReentantReadWriteLock

    2019独角兽企业重金招聘Python工程师标准>>> ReentantReadWriteLock读写锁,在读线程多余写线程的并发环境中能体现出优异的性能,相比于synchroniz ...

  7. Parcelab 和 Serializable

    2019独角兽企业重金招聘Python工程师标准>>> Parcelable 效率高,但不能用于在磁盘存储的情况,因为 Parcelable 不能很好的保证数据的持续性在外界有变化的 ...

  8. 为什么要继承Serializable类?

    为什么要实现Serializable? 最重要的两个原因是: 1.将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本: 2.按值将对象从一个应用程序域发送至另一个应用程序域. 通俗的说 ...

  9. 我对序列化(Serializable)的理解

    转自:http://blog.tianya.cn/blogger/post_show.asp?BlogID=764&PostID=3231409 序列化是把一个对象的状态写入一个字节流的过程. ...

最新文章

  1. 被强制007加班!他愤而把加班证据发给国外供应商和大客户!客户纷纷取消订单!他去度假,老板气疯!...
  2. SpringMVC学习总结(2)——SpringMVC返回json配置
  3. 用java建立多项式logit模型_使用mgcv向多项式logit模型添加样条
  4. UNITY IMGUI
  5. 2021-11-14Collection
  6. set_error_handler自定义错误处理
  7. 快速解决:阿里云ECS实例远程桌面连接 发生身份验证错误。要求的函数不受支持 !
  8. linux系统安装并配置oracle客户端
  9. CTO@全体成员,未经允许和评审不让用反射,Java反射到底慢在哪?
  10. 8,EasyNetQ-多态发布和订阅
  11. 小甲鱼鱼c论坛python作业_[全套55讲]鱼C论坛小甲鱼Python课后题试题.doc
  12. 系统计算机怎么恢复出厂设置,电脑怎么恢复出厂设置 电脑恢复出厂设置的方法 - 云骑士一键重装系统...
  13. 2022山东健博会,食疗养生与滋补健康展,健康管理与精准医学展
  14. iOS安全攻防(二十):越狱检测的攻与防
  15. matlab滤波有几种形式,几种经典常用的滤波算法
  16. html5 中scale函数,javascript中scale怎么使用?
  17. Vue3.0源码解读 - 响应式系统
  18. 现今活跃在信息技术领域的卓越作者--张亚飞新作上市
  19. ST-DBSCAN算法简述及其python实现
  20. D - 折线分割平面 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d %I64u

热门文章

  1. iOS iPhone、iPad、Mac等禁止系统摄像头功能
  2. [Migrated]榜样
  3. homebrew/dupes was deprecated. This tap is now empty as all its formulae were migrated
  4. VMWare删除虚拟机
  5. 简历里的期望薪资应该写多少比较合适呢
  6. 驾考通-小型汽车考试
  7. 计算机硬盘写入量,如何查询固态硬盘SSD的总写入量?
  8. H5开发在微信浏览器上,加载时“白屏”问题
  9. 华为很快搭载鸿蒙系统,华为高管确认很快将会推出搭载鸿蒙操作系统的智能手表...
  10. 子系统kali安装桌面