ObjectInputStream 和 ObjectOutputStream 介绍

ObjectInputStream 和 ObjectOutputStream 的作用是,对基本数据和对象进行序列化操作支持。
创建“文件输出流”对应的ObjectOutputStream对象,该ObjectOutputStream对象能提供对“基本数据或对象”的持久存储;当我们需要读取这些存储的“基本数据或对象”时,可以创建“文件输入流”对应的ObjectInputStream,进而读取出这些“基本数据或对象”。
注意: 只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能被ObjectInputStream/ObjectOutputStream所操作!

本章,我们对序列化进行深入的学习和探讨。学习内容,包括序列化的作用、用途、用法,以及对实现序列化的2种方式SerializableExternalizable的深入研究。

1. 序列化的作用和用途

序列化,就是为了保存对象的状态;而与之对应的反序列化,则可以把保存的对象状态再读出来
简言之:序列化/反序列化,是Java提供一种专门用于的保存/恢复对象状态的机制。

一般在以下几种情况下,我们可能会用到序列化:
a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; 
b)当你想用套接字在网络上传送对象的时候; 
c)当你想通过RMI传输对象的时候。

 

 

我们在介绍序列化定义时,说过“序列化/反序列化,是专门用于的保存/恢复对象状态的机制”。
从中,我们知道:序列化/反序列化,只支持保存/恢复对象状态,即仅支持保存/恢复类的成员变量,但不支持保存类的成员方法!
但是,序列化是不是对类的所有的成员变量的状态都能保存呢?
答案当然是否定的
(01) 序列化对static和transient变量,是不会自动进行状态保存的。
        transient的作用就是,用transient声明的变量,不会被自动序列化。
(02) 对于Socket, Thread类,不支持序列化。若实现序列化的接口中,有Thread成员;在对该类进行序列化操作时,编译会出错!
        这主要是基于资源分配方面的原因。如果Socket,Thread类可以被序列化,但是被反序列化之后也无法对他们进行重新的资源分配;再者,也是没有必要这样实现。

下面,我们还是通过示例来查看“序列化对static和transient的处理”。

 

现在,我们更加确认“序列化不对static和transient变量进行状态保存”。但是,若我们想要保存static或transient变量,能不能办到呢?
当然可以!我们在类中重写两个方法writeObject()和readObject()即可。下面程序演示了如何手动保存static和transient变量。

 
具体细节通过debug可以发现如下调用顺序:
writeObject调用writeObject0(obj, false)调用writeOrdinaryObject(obj, desc, unshared);调用writeSerialData(obj, desc);调用slotDesc.invokeWriteObject(obj, this);调用 writeObjectMethod.invoke(obj, new Object[]{ out });
可见是反射调用。
 

“序列化不会自动保存static和transient变量”,因此我们若要保存它们,则需要通过writeObject()和readObject()去手动读写。


(01) 通过writeObject()方法,写入要保存的变量。writeObject的原始定义是在ObjectOutputStream.java中,我们按照如下示例覆盖即可:

7. Externalizable和完全定制序列化过程

如果一个类要完全负责自己的序列化,则实现Externalizable接口,而不是Serializable接口。

Externalizable接口定义包括两个方法writeExternal()与readExternal()。需要注意的是:声明类实现Externalizable接口会有重大的安全风险。writeExternal()与readExternal()方法声明为public,恶意类可以用这些方法读取和写入对象数据。如果对象包含敏感信息,则要格外小心。

下面,我们修改之前的SerialTest1.java测试程序;将其中的Box由“实现Serializable接口” 改为 “实现Externalizable接口”。

 

说明

(01) 实现Externalizable接口的类,不会像实现Serializable接口那样,会自动将数据保存。
(02) 实现Externalizable接口的类,必须实现writeExternal()和readExternal()接口!
否则,程序无法正常编译!
(03) 实现Externalizable接口的类,必须定义不带参数的构造函数!
否则,程序无法正常编译!
(04) writeExternal() 和 readExternal() 的方法都是public的,不是非常安全!

ObjectStream 及 序列化 介绍的更多相关文章

  1. Netty 粘包 & 拆包 & 编码 & 解码 & 序列化 介绍

    目录: 粘包 & 拆包及解决方案 ByteToMessageDecoder 基于长度编解码器 基于分割符的编解码器 google 的 Protobuf 序列化介绍 其他的 前言 Netty 作 ...

  2. 021.12 IO流 ObjectStream对象序列化

    内容:通过文件存储对象我们遇到的问题,需要保存对象到硬盘中,如何解决这个就是用来解决的 用法:1.创建流对象FileOutputstream2.创建ObjectOutputStream对象与FileO ...

  3. Python--day72--Django内置的serializers序列化介绍

    序列化 Django内置的serializers def books_json(request): book_list = models.Book.objects.all()[0:10] from d ...

  4. c# 与 Unity3d 中的序列化

    圣典中对于Unity3D的序列化介绍很容易和C#的序列化介绍搞混,做个笔记,方便以后查找. 很多资料算是拾人牙慧. 一.Serializable 序列化 Inherits from Attribute ...

  5. C#序列化与反序列化。

    序列化介绍: 把对象用一种新的格式来表示. 系列化只序列化数据. 序列化不建议使用自动属性 为什么要序列化: 将一个复杂的对象转换流,方便存储与信息交换. class Program { static ...

  6. 序列化+protobuff+redis

    背景: 当redis里面需要存储 “key-字符串,value-对象” 时,是不能直接存对象,而是需要将序列化后的对象存进redis. redis没有实现内部序列化对象的功能,所以需要自己提前序列化对 ...

  7. C++序列化使用

    error C2248 无法访问私有成员 :原因 ifstream 作为参数必须传引用! (1):C++使用STL序列化:原文链接:http://blog.csdn.net/pandaxcl/arti ...

  8. Java HashMap源码详解

    Java数据结构-HashMap 目录 Java数据结构-HashMap 1. HashMap 1.1 HashMap介绍 1.1.1 HashMap介绍 1.1.2 HashMap继承图 1.2 H ...

  9. Java中的数据结构-HashMap

    Java数据结构-HashMap 目录 Java数据结构-HashMap 1. HashMap 1.1 HashMap介绍 1.1.1 HashMap介绍 1.1.2 HashMap继承图 1.2 H ...

随机推荐

  1. Javascript模拟继承(赠送.net吐槽一段)

    首先吐槽一句,今年的就业形势很不乐观啊,特别是搞.net的(相对java),特特别是还没出校门没有正式工作经验的,找个实习很难,前些天接了个面试电话,上来就质疑我“你一个在校大学生怎么可能做了那么多项 ...

  2. Android APK是否需要预解压

    今天在逛论坛的时候,发现有一个朋友问的问题.其主要目的,是想实现 玩家首次进入游戏的时候,或者新安装了版本的时候,对APK进行解压,写入SD卡.这样游戏运行过程中,将不会再从APK中读取资源. 以提高 ...

  3. gulp使用小结(一)

    这篇文章不会介绍 gulp 的起源.发展:不会去一个个讲解 gulp API:也不想出现大段大段的 gulpfile.js 代码:更木有帮你分析 gulp 实现原理,只有一些我自己对 gulp 的使用 ...

  4. iOS创建安全的单例

    创建安全的单例 #import "Singleton.h" @implementation Singleton static Singleton* _instance = nil; ...

  5. IOS数据存储之NSUserDefaults

    前言: 作为从事Android开发人来说一定听说过SharedPreferences,然后要成为一名ios开发工程师来说咋能不知道NSUserDefaults!接下来让我们认识一下. NSUserDe ...

  6. Attach Volume 操作(Part I) - 每天5分钟玩转 OpenStack(53)

    上一节我们创建了 volume,本节讨论如何将 volume attach 到 Instance,今天是第一部分. Volume 的最主要用途是作为虚拟硬盘提供给 instance 使用.Volume ...

  7. linux安装和配置 mysql、redis 过程中遇到的问题记录

    linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starting MySQL.The serv ...

  8. 近期博客内容的规划(关于Swift语言)

    因为最近事情比较多,有一段时间没有发表博客了.前一段时间,利用空余时间翻译了一本关于Swif的书籍,过一段时间就会出版吧.通过翻译此书,英语水平没提高多少,不过Swift算是系统的学习了一下. 在翻译 ...

  9. 从零开始构建 Wijmo & Angular 2 小应用

    中秋之际,Angular 团队发布 Angular 2 正式版,一款不错的图表控件Wijmo当天宣布支持 . Angular 2移除和替代了 Angular 1.X 中的 directives, co ...

  10. ios多线程-GCD基本用法

    ios中多线程有三种,NSTread, NSOperation,GCD 这篇就讲讲GCD的基本用法 平时比较多使用和看到的是: dispatch_async(dispatch_get_global_q ...