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. SharpFileDB - a file database for small apps

    SharpFileDB - a file database for small apps 本文中文版在此处. I'm not an expert of database. Please feel fr ...

  2. 关于分工的思考 (Thoughts on Division of Labor)

    Did you ever have the feeling that adding people doesn't help in software development? Did you ever ...

  3. Python模拟HttpRequest的方法总结

    Python可以说是爬网的利器,本文主要介绍了一些python来模拟http请求的一些方法和技巧. Python处理请求的类库有两个,urllib,urllib2. 这两个类库并不是一个类库的两个不同 ...

  4. ASP.NET MVC 5 - 创建连接字符串(Connection String)并使用SQL Server LocalDB

    您创建的MovieDBContext类负责处理连接到数据库,并将Movie对象映射到数据库记录的任务中.你可能会问一个问题,如何指定它将连接到数据库? 实际上,确实没有指定要使用的数据库,Entity ...

  5. SQL语句全

    创建数据库 创建之前判断该数据库是否存在 if exists (select * from sysdatabases where name='databaseName') drop database ...

  6. defered,promise回顾

    defered,promise回顾 http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_o ...

  7. Dynatree使用

    最近用到了Dynatree的树形结构,记录一下它的用法. 需求: 1.jquery.js 2.jquery-ui.custom.js 3.jquery.cookie.js 下载dynatree,放到资 ...

  8. MongoDB replica set IDs do not match

    在搭建MongoDB(版本 3.2.9)的Replica Set时,使用 rs.status() 查看Replica Set的状态,发现一个成员异常:replica set IDs do not ma ...

  9. SSRS3: Credentials配置

    1,Service Account Service Account 是Reporting Service 运行的账户,可以通过查看Windows 的 Service 来查看,强烈建议使用 Report ...

  10. 【Win10 开发】读取PDF文档

    关于用来读取PDF文档的内容的API,其实在Win8.1的时候就有,不过没关系,既咱们讨论的是10的UAP,连同8.1的内容也包括进去,所以老周无数次强调:把以前的内容学好了,就可以在不学习任何新知识 ...