`
sharajava
  • 浏览: 67094 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

序列化到底是怎么回事

    博客分类:
  • Java
阅读更多

有感:花了7年多时间才感悟到什么样才是一个真正的程序员。

“研究”了那么多“高深”的东西后才发现,原来“低级”的基础是那么重要。

面对基础,我又是那么无知。

 

所谓Java的序列化是指,Java对象(注意是对象、对象)可以被编码成字节码的形式(主要用于存储或传输),同时可以进行逆向的操作,“反”序列化成JVM中的对象。

 

当然,不是所有的Java对象都可以序列化:必须实现java.io.Serializable接口。

 

把对象序列化做什么用呢?

一方面,在分布的Java平台之意传递信息(Java对象);另外一方面,实现深度克隆一个Java对象。

 

估计80%的人也就理解到上述这些内容。

 

应用序列化的过程中,遇到关于序列化ID的问题,经过试验,得出一些心得,还写了博文:

http://sharajava.iteye.com/blog/102886

 

但实际上,现在才觉得可笑,Serializable的JavaDoc文档中就清楚地写明白着呢,如果早看,早就明白了。

 

其实,JavaDoc里一开始就表达到非常基础且重要的问题,自己却一直没考虑到过的:如果继承一个未实现序列化接口的类,子类实现序列化接口,那么父类的属性(成员变量)哪些被序列化,哪些不被序列化呢?

 

 写道
protected, and (if accessible) package fields
 

 

细想想,很自然的事情,除了private的,都是在子类序列化范围内的。父类私有的对于子类也是不可见的,当然也就犯不上在序列化过程中包含它们。

另外,这里面还有一个很重要的限制:父类必须具备一下“无参数”的构建函数,以使得子类在(反)序列化过程中创建父类实例。

 

 写道
During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class.

 

我们都知道,java.io.Serializable接口是一个声明式的接口,没有接口方法是必须实现的。

但就像序列化ID(serialVersionUID)一样,在实现这个接口的同时,我们还是有很多与Java平台的“约定”可以做一些事情的。  

 

比较直接可以想到,序列化和反序列化的过程,实际上也就是IO流“读写”过程而已。我们可以分别声明并实现两个特定的方法,参与到序列化和反序列化的过程中。

 

 private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

write方法是序列化的过程,read方法是反序列化的过程。参数中的Stream(对象流)就是过程中,类对象的实际内容。

也就是说,Java平台会在序列化和反序列化的过程中分别调用这两个方法。

当然,我们一般也只是需要“额外”做一些事情,核心的内容还是希望保持缺省的机制,我们就有可以调用两个参数输入、输出流的defaultWriteObject方法和defaultReadObject方法。 

 

上面这些内容,实际上用处还不是很大,至少我在开发过程中还没有什么需要一定要在这些机制上“做手脚”。

但在深入研究“单例”的问题时,遇到了下面这样的情况:单例

 

我们都知道,单例是希望在一定范围(一个类加载器)内,对于某类的实例仅有一个唯一的对象实例。

实现单例模式的方法很多,这里不多说,唯独如果希望实现单例的类实现了序列化接口,会出现什么样的问题?

我把单例的实例,在同一个应用范围内,序列化,再反序列化回来,不是又得到一个该类的对象?这样不就不是单例了吗?

 

不用担心,序列化机制还提供了两个方法:

 

 ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
 ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
 

这两个方法可以理解为序列化和反序列化过程的入口和出口。writeReplace()返回的对象,就是要被序列化的对象,我们有机会在序列化前把这个对象给换成我们确定好的那个(如果不是“故意捣乱”,暂时没想到有什么用);而readResolve()方法就是在反序列化完成得到对象前,把这个对象给换成我们确定好的那个。

明白了吧?为了防止有人恶意通过序列化的机制破坏定义好的单例,我们就需要自己实现readResolve()方法,把单例定义的唯一实现在这个方法中返回。

 

对于序列化机制,我想基本有上述理解才能算得上理解吧?

其实真的没有什么特别的需要,只要仔细读一读JavaDoc即可,而我们大多数人(包括我自己)都往往忽略了这些所谓的基础。

 

 

 

 

分享到:
评论

相关推荐

    C++ JSON 序列化与反序列化

    本篇文章将深入探讨C++中JSON的序列化与反序列化。 **一、JSON序列化** 序列化是指将C++的对象转换为JSON字符串的过程,以便在网络上传输或保存到文件中。常见的C++ JSON序列化库有RapidJSON、nlohmann/json、...

    java 对象的序列化与反序列化

    Java对象的序列化和反序列化是Java编程中一项重要的技术,主要用于将对象的状态转换为字节流,以便存储或在网络上传输。这一过程对于理解Java的IO操作、持久化数据以及实现分布式通信等场景非常关键。 首先,我们来...

    java序列化和反序列化的方法

    序列化是将对象转换为字节流的过程,而反序列化是将字节流转换回对象的过程。 在 Java 中,序列化和反序列化是通过实现 Serializable 接口来实现的。Serializable 接口是一个标记接口,不包含任何方法,但它告诉 ...

    C#和Java的序列化反序列化

    在编程领域,序列化和反序列化是两个关键的概念,特别是在跨平台通信、持久化存储以及数据传输中扮演着重要角色。本篇文章将深入探讨C#和Java中的序列化与反序列化机制。 首先,我们要了解什么是序列化。序列化是指...

    XML序列化与反序列化 实战

    这个类可能包含了一些方法,如`Serialize`(将对象序列化为XML字符串或写入XML文件)和`Deserialize`(从XML字符串或文件反序列化回对象)。 接下来,`说明.txt`文件应该提供了关于如何使用这个项目的详细指南。它...

    ASPNET中JSON的序列化和反序列化的方法

    反序列化时,你需要将这个字符串转换回`DateTime`对象,这通常需要自定义转换逻辑或使用特定的方法。 综上所述,在***中实现JSON的序列化和反序列化,可以通过内置的`DataContractJsonSerializer`类或使用第三方库...

    序列化和反序列化的封装类

    在编程领域,序列化和反序列化是两个关键的概念,特别是在数据存储、网络传输和对象持久化等场景中。它们允许我们将对象的状态转换为字节流(序列化),然后在需要的时候将字节流还原为原来的对象(反序列化)。在C#...

    序列化和反序列化dll文件和proto

    它们涉及将对象的状态转换为可持久化的格式(序列化),以及将这种格式还原回原来的对象(反序列化)。本文将深入探讨这两种技术在处理DLL文件和Protocol Buffers(proto)时的应用。 首先,DLL(Dynamic Link ...

    基于boost的序列化与反序列化

    在编程领域,序列化和反序列化是两个关键的概念,它们用于将对象的状态转换为可存储或可传输的格式,然后在需要时恢复为原始对象。Boost库提供了一个强大的工具——Boost.Serialization,来帮助程序员实现这个功能。...

    hessian学习基础篇——序列化和反序列化

    在IT领域,序列化和反序列化是两个关键的概念,特别是在网络通信、数据持久化以及对象存储中。本文将深入探讨Hessian框架的基础知识,它是一个高效的二进制序列化协议,广泛应用于Java和.NET之间跨语言通信。通过...

    hashtable序列化与反序列化

    反序列化是将字节流转换回原来的对象状态的过程。在Java中,可以使用`ObjectInputStream`来实现这个功能: ```java try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hashTable.ser"))) {...

    序列化与反序列化

    在计算机科学领域,序列化和反序列化是两个至关重要的概念,特别是在数据传输、存储以及对象持久化等场景。这两个过程对于理解数据流如何在内存、磁盘和网络之间转换至关重要。 序列化是指将对象的状态转化为可存储...

    java序列化(Serializable)的作用和反序列化.doc

    ### Java序列化(Serializable)的作用与反序列化详解 #### 一、序列化的概念 序列化是指将程序中的对象转换为一系列字节流的过程,主要用于保存对象的状态或在网络之间传输对象。序列化的主要目的是为了能够持久化...

    java反序列化工具

    Java反序列化是一种将已序列化的对象状态转换回对象的过程,它是Java平台中持久化数据的一种常见方式。在Java应用程序中,序列化用于保存对象的状态以便稍后恢复,或者在网络间传输对象。然而,这个过程也可能引入...

    delphi序列化与反序列化

    在IT行业中,序列化和反序列化是两个关键的概念,特别是在对象持久化、数据传输以及存储方面。在Delphi编程环境中,这两个概念同样至关重要。本文将深入探讨Delphi中的序列化与反序列化,以及如何处理组件和结构体的...

    四种反序列化与序列化

    - **DataContractSerializer反序列化**:同样,它也能将XML反序列化回对象,使用 `ReadObject` 方法完成此操作。 以上四种序列化与反序列化方法各有优缺点,适用于不同场景。XML和JSON适合跨平台的数据交换,而...

    C#序列化与反序列化(包括复杂xml对象)

    本文将深入探讨C#中的XML序列化和反序列化技术,包括如何将XML文档解析为对象,以及如何将对象转换回XML文档进行存储。我们将详细讲解三种方法,涵盖从XML节点获取键值对(KV值)到处理对象数组和节点标签组合的反...

    jackson json序列化,反序列化所需jar包

    反序列化则是将JSON字符串转换回Java对象,你可以使用`readValue()`方法: ```java MyObject obj = mapper.readValue(jsonString, MyObject.class); ``` 在实际开发中,你可能还需要配置`ObjectMapper`以满足特定...

    C# 序列化反序列化

    在编程领域,序列化和反序列化是两个关键的概念,特别是在C#中。它们用于将对象的状态转换为可存储或可传输的形式,如文本或二进制数据,然后能够恢复成原来的对象。在这个特定的场景中,我们看到的是一个利用C#进行...

    序列化反序列化例题net

    在.NET框架中,序列化和反序列化是两个重要的概念,它们主要用于数据持久化、网络传输和跨进程通信。理解并熟练运用这些技术对于任何.NET开发者来说都是至关重要的。 序列化是将对象的状态(包括其属性和字段)转换...

Global site tag (gtag.js) - Google Analytics