对象序列化是什么

对象序列化(Serialize)指将一个 Java 对象写入 IO 流中,与此对应的是,对象的反序列化(Deserialize)则指从 IO 流中恢复该 Java 对象。如果想让某个 Java 对象能够序列化,则必须让它的类实现 java.io.Serializable 接口,接口定义如下:

public interface Serializable {}

Serializable 接口是一个空接口,实现该接口无须实现任何方法,它只是告诉 JVM 该类可以被序列化机制处理。通常建议程序创建的每个 JavaBean 类都实现 Serializable。

ObjectInput 接口与 ObjectOutput 接口分别继承了 DataInput 和 DataOutput 接口,主要提供用于读写基本数据和对象数据的方法。

ObjectInput 接口提供了 readObject() 方法,此方法用于将对象从流中读出

ObjectOutput 提供了 writeObject() 方法,此方法用于将对象写入流中。

因为 ObjectInput 与 ObjectOutput 都是接口,所以不能创建对象,只能使用分别实现了这两个接口的 ObjectInputStream 类和 ObjectOutputStream 类来创建对象。

下面讲解如何使用 ObjectInputStream 类和 ObjectOutputStream 类来操作数据。

序列化

ObjectOutputStream 类继承了 OutputStream 类,同时实现了 ObjectOutput 接口,提供将对象序列化并写入流中的功能,该类的构造方法如下:

public ObjectOutputStream (OutputStream out)

该构造方法需要传入一个 OutputStream 对象,用来表示将对象二进制流写入到指定的 OutputStream 中。

程序通过以下两个步骤来序列化对象:

1)创建一个 ObjectOutputStream 对象,如下代码所示。

// 创建个 ObjectOutputStream 输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));

2)调用 ObjectOutputStream 对象的 writeObject() 方法输出可序列化对象,如下代码所示。
// 将一个 Person 对象输出到输出流中

oos.writerObject(per);

例 1
下面程序定义了一个 Person 类,这个 Person 类就是一个普通的 Java 类,只是实现了 Serializable 接口,该接口表示该类的对象是可序列化的。

import java.io.Serializable;
public class Person implements Serializable {private String name;private int age;// 注意此处没有提供无参数的构造器public Person(String name, int age) {System.out.println("有参数的构造器");this.name = name;this.age = age;}// 省略 name 和 age的setter和getter方法...
}

注意:Person 类的两个成员变量分别是 String 类型和 int 类型的。如果某个类的成员变量的类型不是基本类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型成员变量的类也是不可序列化的。

下面程序使用 ObjectOutputStream 将一个 Person 对象写入到磁盘文件。

public class WriteObject {public static void main(String[] args) throws Exception {// 创建一个 ObjectOutputStream 输出流ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));Person per = new Person("你好你好你好", 7);// 将 Per对象写入输出流oos.writeObject(per);}
}

上面程序中的第 4 行代码创建了一个 ObjectOutputStream 输出流,这个 ObjectOutputStream 输出流建立在一个文件输出流的基础之上。程序第 7 行代码使用 writeObject() 方法将一个 Person 对象写入输出流。运行上面程序,将会看到生成了一个 object.txt 文件,该文件的内容就是 Person 对象。

反序列化

ObjectInputStream 类继承了 InputStream 类,同时实现了 ObjectInput 接口,提供了将对象序列化并从流中读取出来的功能。该类的构造方法如下:

public ObjectInputStream(InputStream out)

该构造方法需要传入一个 InputStream 对象,用来创建从指定 InputStream 读取的 ObjectInputStream。

反序列化的步骤如下所示:

1)创建一个 ObjectInputStream 输入流,这个输入流是一个处理流,所以必须建立在其他节点流的基础之上。如下代码所示。

// 创建一个ObjectInputStream输入流
ObjectInputStream ois = new ObjectInputStream (new FileInputStream ("object. txt"));

2)调用 ObjectInputStream 对象的 readObject() 方法读取流中的对象,该方法返回一个 Object 类型的 Java 对象,如果程序知道该 Java 对象的类型,则可以将该对象强制类型转换成其真实的类型。如下代码所示。

// 从输入流中读取一个Java对象,并将其强制类型转换为Person类
Person P = (Person)ois.readObject();

例 2
下面程序是从例 1 中生成的 object.txt 文件来读取 Person 对象的步骤。

public class ReadObject {public static void main(String[] args) throws Exception {// 创建一个ObjectInputStream输入流ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));// 从输入流中读取一个 Java对象,并将其强制类型转换为Person类Person p = (Person) ois.readObject();System.out.println("名字为:" + p.getName() + "\n年龄为:" + p.getAge());}
}

上面程序中第 4 行粗体字代码将一个文件输入流包装成 ObjectInputStream 输入流,第 6 行代码使用 readObject() 读取了文件中的 Java 对象,这就完成了反序列化过程。

反序列化读取的仅仅是 Java 对象的数据,而不是 Java 类,因此采用反序列化恢复 Java 对象时,必须提供该 Java 对象所属类的 class 文件,否则将会引发 ClassNotFoundException 异常。

Person 类只有一个有参数的构造器,没有无参数的构造器,而且该构造器内有一个普通的打印语句。当反序列化读取 Java 对象时,并没有看到程序调用该构造器,这表明反序列化机制无须通过构造器来初始化 Java 对象。

如果使用序列化机制向文件中写入了多个 Java 对象,使用反序列化机制恢复对象时必须按实际写入的顺序读取。

当一个可序列化类有多个父类时(包括直接父类和间接父类),这些父类要么有无参数的构造方法,要么也是可序列化的,否则反序列化时将抛出 InvalidClassException 异常。如果父类是不可序列化的,只是带有无参数的构造方法,则该父类中定义的成员变量值不会序列化到 IO 流中。

Java序列化编号

Java 序列化机制是通过类的序列化编号(serialVersionUID)来验证版本一致性的。在反序列化时,JVM 会把传来字节流中的序列化编号和本地相应实体类的序列化编号进行比较,如果相同就认为一致,可以进行反序列化,否则会抛出 InvalidCastException 异常

序列化编号有两种显式生成方式:

  • 默认的1L,比如:private static final long serialVersionUID = 1L。
  • 根据类名、接口名、成员方法及属性等来生成一个 64 位的哈希字段。

当实现 Serializable 接口的对象没有显式定义一个序列化编号时,Java 序列化会根据编译的 Class 自动生成一个序列化编号,这种情况下只要 class 文件发生变化,序列化号就会改变,否则一直不变。

1.10 对象序列化控制输入输出相关推荐

  1. 理解Java对象序列化——Serializable接口

    概述:当一个类实现了Serializable接口(该接口仅为标记接口,不包含任何方法定义),表示该类可以序列化.序列化的目的是将一个实现了Serializable接口的对象转换成一个字节序列,可以. ...

  2. C#对象序列化与反序列化zz

    C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍.......................... ...

  3. C#对象序列化与反序列化

    C#对象序列化与反序列化 C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍............. ...

  4. Thinking in java 琐碎知识点之 I/O流 、对象序列化

    Java I/O流 .对象序列化 1.File类    此类的实例可能表示(也可能不表示)实际文件系统对象,如文件或目录.    File类可以新建.删除和重命名文件和目录,但是File不能访问文件本 ...

  5. 12、数据系统内置功能(字符串、数组、时间、Math、遍历器、对象成员检测、Object静态方法、对象序列化、正则表达式)

    目录 12.1字符串 12.1.1特效标签 12.1.2字符串截子串 12.2 数组 12.3时间 12.4Math 12.5遍历器 1.for 循环 2.for in 循环  (es5的技术) 3. ...

  6. Java对象序列化与反序列化

    什么是序列化与反序列化 当两个进程在进行远程通信时,彼此可以发送各种类型的数据.无论是何种类型的数据,都会以二进制序列的形式在网络上传送.发送方需要把这个Java对象转换为字节序列,才能在网络上传送: ...

  7. 使用C++进行对象序列化

    1 什么是序列化 程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯.这个将程序数据转化成能被存储并传输的格式的过程被称 ...

  8. 基于Golang的对象序列化的程序包开发——myJsonMarshal

    基于Golang的对象序列化的程序包开发--myJsonMarshal[阅读时间:约10分钟] 一.对象序列化概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 三.具体程序设计及 ...

  9. .NET 中的对象序列化 (转载)

    .NET 中的对象序列化 Piet Obermeyer Microsoft Corporation 2001 年 8 月 摘要:为什么要使用序列化?最重要的两个原因是:将对象的状态保存在存储媒体中以便 ...

最新文章

  1. python 面向对象学习
  2. 企业USB权限控制心得
  3. Mac版本Navicat下载
  4. python报错 scrolled: false_python 元组tuple - python基础入门(14)
  5. Concurrent HTTP connections in Node.js
  6. [链表遍历|模拟] leetcode 2 两数相加
  7. springmvc json结合
  8. Linux ct获取本机ip,[原]archlinux 下最新的netct工具配置ip地址
  9. 服务器字体放在服务器什么位置,服务器缺少字体如何查看与添加
  10. 3U VPX高性能数据处理板(XC7K325T FMC载板)
  11. alpha在matlab中啥意思,alpha是什么
  12. 智能型炉温测试仪kic x5软件,KIC X5 炉温测试仪产品说明ppt课件
  13. 解决部署Hexo后出现的The custom domain for your GitHub Pages site is pointed at an outdated IP address警告
  14. More Effective C++之 Item M35:让自己习惯使用标准C++语言
  15. 从零学习 InfiniBand-network架构(三) —— IB核心传输引擎Queue Pair
  16. delphi xml 万一 blog
  17. 面试英语自我介绍的常用基本的句子
  18. 西部数码确实挺强大,系统很方便,…
  19. 啊哈~花一天快速上手Pytorch(可能是全网最全流程从0到部署)
  20. [ios版本]AR 现实增强之高通Vuforia

热门文章

  1. Crawler:基于splinter.browser库实现爬取12306网站来实现快速抢票
  2. Funny:还是程序猿会玩——弹幕炸天学AI和区块链,玩起来!弹慕君,你也值得拥有!
  3. WRF,WPS,WRF-Chem安装及编译步骤及bug总结(2)
  4. python中多进程+协程的使用以及为什么要用它
  5. 十进制转换成二进制列表
  6. WinForm读取相对路径(项目文件)下的图片
  7. Angular2.0 基础: Form
  8. PPM / PGM / PBM 图像文件格式
  9. (转)几种流行的JS框架的选择
  10. Web Service 学习笔记(2)