Java-理论知识之串行化
对对象进行串行化的方法有两种 : 1 Serializable接口 2 Externalizable接口 (安卓的对象串行化还可以使用Parcelable接口,方法与Serializable接口类似)
1 Serializable接口
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
简而言之就是可以通过ObjectOutputStream 把调用java.io.Serializable接口的类的对象写入流中,而在流的另一端取出这个对象来。也可以把对象写到文件里,以后再读出来。
实现串行化需要注意的条件:
1. 输入流写入的类的对象的方法与输出流的类的对象的方法必须名字、类型、修饰符完全一致,方法里面的内容可以不同。 (方法)(保证serialVersionUID一致)
2. 输入流的对象与输出流的对象字段必须一致,包括修饰符。 (字段)
3. 输入流的的对象的类与输出流对象的类必须一致,包括名字。 (类)
4. 不需要写入流的字段用transient修饰。
5. 串行化不会写入静态变量,成员方法不会被保存。
总而言之,串行化就是按格式传数据/读数据或写数据/读数据的。
如果想自定义数据传输的顺序,在实现Serializable接口的类中重写下面2种方法:
- private void readObject(ObjectInputStream in)
- {
- }
- private void writeObject(ObjectOutputStream out)
- {
- }
上面一个是写的方法,一个是读的方法。
下面是从源码中截取的一段:
- if (obj instanceof String) {
- writeString((String) obj, unshared);
- } else if (cl.isArray()) {
- writeArray(obj, desc, unshared);
- } else if (obj instanceof Enum) {
- writeEnum((Enum) obj, desc, unshared);
- } else if (obj instanceof Serializable) {
- writeOrdinaryObject(obj, desc, unshared);
- } else {
- if (extendedDebugInfo) {
- throw new NotSerializableException(
- cl.getName() + "\n" + debugInfoStack.toString());
- } else {
- throw new NotSerializableException(cl.getName());
- }
- }
Enum 常量的序列化不同于普通的 serializable 或 externalizable 对象。enum 常量的序列化形式只包含其名称;常量的字段值不被传送。为了序列化 enum 常量,ObjectOutputStream 需要写入由常量的名称方法返回的字符串。与其他 serializable 或 externalizable 对象一样,enum 常量可以作为序列化流中后续出现的 back 引用的目标。用于序列化 enum 常量的进程不可定制;在序列化期间,由 enum 类型定义的所有类特定的 writeObject 和 writeReplace 方法都将被忽略。类似地,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略,所有 enum 类型都有一个 0L 的固定的 serialVersionUID。
2 Externalizable接口
被Serializable接口声明的类的对象的内容都将被序列化,如果现在用户希望自己指定序列化的内容,则可以让一个类实现Externalizable接口,此接口定义如下:
- public interface Externalizable extends Serializable {
- public void writeExternal(ObjectOutput out) throws IOException ;
- public void readExternal(ObjectInput in) throws IOException,
- ClassNot FoundException ;
- }
Externalizable接口是Serializable接口的子接口,在此接口中定义了两个方法,这两个方法的作用如下。
writeExternal(ObjectOutput out):在此方法中指定要保存的属性信息,对象序列化时调用。
readExternal(ObjectInput in):在此方法中读取被保存的信息,对象反序列化时调用。
这两个方法的参数类型是ObjectOutput和ObjectInput,两个接口的定义如下。
ObjectOutput接口定义:
- public interface ObjectOutput extends DataOutput
ObjectInput接口定义:
- public interface ObjectInput extends DataInput
可以发现以上两个接口分别继承DataOutput和DataInput,这样在这两个方法中就可以像DataOutputStream和DataInputStream那样直接输出和读取各种类型的数据。
如果一个类要使用Externalizable实现序列化时,在此类中必须存在一个无参构造方法,因为在反序列化时会默认调用无参构造实例化对象,如果没有此无参构造,则运行时将会出现异常,这一点的实现机制与Serializable接口是不同的。
范例:修改Person类并实现Externalizable接口
- package org.lxh.demo12.serdemo;
- import java.io.Externalizable;
- import java.io.IOException;
- import java.io.ObjectInput;
- import java.io.ObjectOutput;
- public class Person implements Externalizable {// 此类的对象可以被序列化
- private String name; // 声明name属性
- private int age; // 声明age属性
- public Person(){} // 必须定义无参构造
- public Person(String name, int age) { // 通过构造方法设置属性内容
- this.name = name;
- this.age = age;
- }
- public String toString() { // 覆写toString()方法
- return "姓名:" + this.name + ";年龄:" + this.age;
- }
- // 覆写此方法,根据需要读取内容,反序列化时使用
- public void readExternal(ObjectInput in) throws IOException,
- ClassNotFoundException {
- this.name = (String)in.readObject() ; // 读取姓名属性
- this.age = in.readInt() ; // 读取年龄
- }
- // 覆写此方法,根据需要可以保存属性或具体内容, 序列化时使用
- public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject(this.name) ; // 保存姓名属性
- out.writeInt(this.age) ; // 保存年龄属性
- }
- }
以上程序中的Person类实现了Externalizable接口,这样用户就可以在类中有选择地保存需要的属性或者其他的具体数据。在本程序中,为了与之前的程序统一,将全部属性保存下来。
范例:序列化和反序列化Person对象
- package org.lxh.demo12.serdemo;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.OutputStream;
- public class SerDemo03 {
- public static void main(String[] args) throws Exception {
- ser(); // 序列化
- dser(); // 反序列化
- }
- public static void ser() throws Exception { // 序列化操作
- File f = new File("D:" + File.separator + "test.txt");
- ObjectOutputStream oos = null;
- OutputStream out = new FileOutputStream(f); // 文件输出流
- oos = new ObjectOutputStream(out); // 为对象输出流实例化
- oos.writeObject(new Person("张三", 30)); // 保存对象到文件
- oos.close(); // 关闭输出
- }
- public static void dser() throws Exception { // 反序列化操作
- File f = new File("D:" + File.separator + "test.txt");
- ObjectInputStream ois = null;
- InputStream input = new FileInputStream(f); // 文件输出流
- ois = new ObjectInputStream(input); // 为对象输出流实例化
- Object obj = ois.readObject(); // 读取对象
- ois.close(); // 关闭输出
- System.out.println(obj);
- }
- }
从以上代码中可以发现,使用Externalizable接口实现序列化明显要比使用Serializable接口实现序列化麻烦得多,除此之外,两者的实现还有不同,如表12-27所示。
表12-27 Externalizable接口与Serializable接口实现序列化的区别
序 号 |
区 别 |
Serializable |
Externalizable |
1 |
实现复杂度 |
实现简单,Java对其 有内建支持 |
实现复杂, 由开发人员自己完成 |
2 |
执行效率 |
所有对象由Java统一保存, 性能较低 |
开发人员决定哪个对象保存, 可能造成速度提升 |
3 |
保存信息 |
保存时占用空间大 |
部分存储, 可能造成空间减少 |
在一般的开发中,因为Serializable接口的使用较为方便,所以出现较多
Java-理论知识之串行化相关推荐
- Java中对象的串行化(Serialization)和transient关键字
Java中对象的串行化(Serialization)和transient关键字 前言: 该篇文章参考自网上资料,但是部分内容经过笔者更改,因此算作原创吧,原文地址: http://www.golden ...
- java input是关键字吗_Java中对象的串行化(Serialization)和transient关键字 - 金色阳光...
Java中对象的串行化(Serialization)和transient关键字: 对象的串行化(Serialization) 一.串行化的概念和目的 1.什么是串行化 对象的寿命通常随着生成该对象的程 ...
- 精通Java事务编程(8)-可串行化隔离级别之可串行化的快照隔离
本系列文章描述了DB并发控制的黯淡: 2PL虽保证了串行化,但性能和扩展不好 性能良好的弱隔离级别,但易出现各种竞争条件(丢失更新,写倾斜,幻读 串行化的隔离级别和高性能就是相互矛盾的吗?也许不是,一 ...
- 数据库理论:ER模型,关系转换,并发控制与冲突可串行化调度
目录 前言 ER模型 实体 属性 关系 参与 关系的度(degree) 一对一与一对多 ER 图符 关系转化(重要) 并发控制 概述 并发控制中的不一致性 修改丢失 不可重复读 脏读 封锁技术 封锁三 ...
- java ado recordset_AdoDataSet.RecordSet的串行化和还原(转载)
标签: //数据集串行化 function RecordsetToXML(const Recordset: _Recordset): string; var RS: Variant; Stream: ...
- PHP串行化与JSON
PHP串行化与JSON 2008年3月19日 评论 发表评论 作者:hanguofeng[小韩] 发布于:经典论坛 玄猫的窝(作者的博客) 在经典论坛的连载地址:http://bbs.blueidea ...
- php串行化,PHP串行化与JSON
来源: 未知 作者: 老苏 2011-07-18/10:23 我还有话要说 先来诠释下串行化:简单来讲,串行化行将变量转换成字节省的进程.串行化的提出,有用的办理了对象的保留和传输的题目,举例来讲,我 ...
- 并发事务正确性的准则 可串行化_从0到1理解数据库事务(上):并发问题与隔离级别...
最近准备写一篇关于Spanner事务的分享,所以先分享一些基础知识,涉及ACID.隔离级别.MVCC.锁,由于太长,只好拆分成上下两篇: 上:并发问题与隔离级别 主要讲事务所要解决的问题.思路,先理解 ...
- 利用XMLSerializer将对象串行化到XML
微软已经意识到串行化数据的重要性,因此在.NET框架中包含了命名空间System.Runtime.Serialization和System.Xml.Serialization以提供串行化功能,为用户自 ...
最新文章
- python全栈脱产第25天------组合、多态、封装、property装饰器
- 如何看exe文件源代码_杀进程、删文件...看新型勒索软件RobbinHood如何干掉杀毒软件...
- python多线程实现同步的方式_深入解析Python中的线程同步方法
- 关于设置不同linux主机之间ssh免密登录简易方法
- 漫步凸分析一——仿射集
- ios 绘制线框_iOS开发 给View添加指定位置的边框线
- Python简易验证码生成程序
- Redis实现微博后台业务逻辑系列(八)
- IOS-UIButton的文本与图片的布局
- Oracle Sql关于case-when,if-then,decode
- 搭建一个网站的价格以及步骤全面解读
- 物联网智能家居系统解决方案
- 【每日面试】2021政采云Java一面
- 联合国 ITU 立项成功,DevOps 标准开启国际化模式!
- 自己的JS框架--Amy框架。
- Flutter开发日常练习-pageview滑动视图动画
- probability是什么意思_probability是什么意思_probability怎么读_probability翻译_用法_发音_词组_同反义词_可能性-新东方在线英语词典...
- 法兰克弧焊机器人,FANUC焊接机器人培训.ppt
- 一种新型双频双圆极化微带天线的设计
- axios 封装 (转)
热门文章
- What are differences between ‘a priori‘ and ‘posteriori‘ error estimate in numerical analysis?
- windows下使用apache bench(ab)进行带多个header信息的post请求压力测试
- 电脑螺旋丸html,code_editor.html
- Java代码生成器codeMan重磅更新——添加权限管理模块生成功能,实现动态菜单和按钮级别的权限控制
- P3243 [HNOI2015]菜肴制作(拓扑排序)
- 回顾之前在上海工作一年
- 创业干货:牛逼的外衣,苦逼的内裤
- 用图像分割制作专属表情包?这里有妙招!
- 2023上半年工作总结
- 华为系统鸿蒙多少个月不卡,华为鸿蒙系统正式领证!你会支持华为手机吗?