java serializable 源码_Java源码分析之-Serializable接口

一、基本概念

Serializable接口:

1. 实现了Serializable接口的类,可以进行序列化和反序列化;没有实现这个接口的类的任何(state)状态/域或者属性值不能被序列化

2. All subtypes of a serializable class are themselves serializable.  所有实现了序列话接口的类的子类是可以被序列化的

3. 为了让不能序列化的类的子类能够被序列化,子类要能够保存和恢复(restore)父类的public/protected和package fields;只有在父类具有无参构造函数去初始化其域的情况下,子类才能保存和恢复父类的public/protectes和package fields;如果不是这种情况,声明一个可序列化的类是有问题的;并且在运行期即可以检测到这个错误;

4.在反序列化的过程中,不能序列化的类对应的域,将会用这个类的public或者protected修饰的无参构造方法进行初始化;无参的构造方法必须是可序列化的子类有访问权限的;可序列化子类的域将从流中恢复回来。

5.在序列化和反序列化的过程中,这些类都需要经过特殊的处理,也就是需要去实现特殊的方法:

* private void writeObject(java.io.ObjectOutputStream out)

* throws IOException

* private void readObject(java.io.ObjectInputStream in)

* throws IOException, ClassNotFoundException;

* private void readObjectNoData()

* throws ObjectStreamException;

*

5.1  WriteObject方法:

1)  WriteObject方法用来将特定类的对象的域写入,这样对应的可读对象可以将这些域恢复回来。

2)默认的存储对象域的机制可以通过调用方法out.defaultWriteObject()来实现,这个方法不需要去将它自己和属于父类或者子类的域相关联起来

3)类的状态通过调用writeObject()方法或者用数据输出(DataOutput)所支持的针对原生(primitive)数据类型的方法来将类所拥有的域写入到对象输出流(ObjectOutputStream)中来保存起来

5.2 readObject方法

1)readObject方法用来读流,并将类的域恢复回来。

2)readObject方法可以调用in.defaultReadObject方法来执行恢复类的没有static和transient修饰的域的默认机制。这个in.defaultReadObject方法利用流中的信息来用当前对象的对应名字的域来分配存储在流中的对象的域。这解决了类在后期增加新的域的情况。

3)类的状态通过调用writeObject()方法或者用数据输出(DataOutput)所支持的针对原生(primitive)数据类型的方法来将类所拥有的域写入到对象输出流(ObjectOutputStream)中来保存起来

5.3 readObjectNoData方法:

1)readObjectNoData方法用来在序列化的流没有列出所给出的类(这个类是被反序列化的对象的一个父类)的情况下去初始化这个类的对象的域。这种情况出现在接受方用了一个和发送方不同版本反序列化实例的类,并且这个接收方的版本所继承的类并没有被发送方的版本所继承;这种情况也可能出现在序列化的流已经被篡改;

2)因此,在有一个不利的或者不完整的流的情况下,readObjectNoData方法对于去合理的初始化反序列化对象是非常有用的

6. 在将一个对象写入到流中的时候,需要指派一个可替代的对象去使用的可序列化类要去实现下面的方法:

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

*

1)如果这个方法存在,那么这个方法应该在被序列化的时候调用

2)这个方法需要能被在类的作用域下的其他方法访问,因此这个方法有public/protected/private访问权限

3)子类访问这个方法遵循java的权限访问规则

7. 当一个类的实例从流读出的时候,这个类需要指派一个可替代的对象,应该要去实现下面的方法:

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

*

机制和writeReplace方法类似

8.序列化版本唯一标识-SerialVersionUID

1. 定义:在序列化运行时期,会将每一个可序列化类和一个版本号关联起来,这个版本号就叫做SerialVersionUID

2. 作用:这个序列化唯一标识的作用是为了式一个可序列化的对象发送方和接收方在装载那个对象的类时相对于序列化是匹配的

3. 当接受方装载了一个对象的类和对应接收方装载的类有不同的序列化唯一标识的时候就会导致InvalidClassException

4. 一个可序列化的类可以显示声明一个SerialVersionUID,这个序列化唯一标识需要被static/final/long修饰

* ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

*

5. 如果一个可序列化的类不显示声明SerialVersionUID,那么将会基于这个类的很多方法计算一个默认的SerialVersionuid值,但是强烈建议显示声明,为了兼容不不同的编译器;也建议SerialVersionUID被private修饰,从而不能被继承,因为继承了也没有很大意义。

6.数组不需要显式声明序列化版本唯一标识,对于数组类而言,需要接收方和发送方的序列化唯一标识是一致的已经被废弃了的。

@author unascribed

* @see java.io.ObjectOutputStream

* @see java.io.ObjectInputStream

* @see java.io.ObjectOutput

* @see java.io.ObjectInput

* @see java.io.Externalizable

* @since JDK1.1

*/

public interface Serializable {

}

二、序列化和反序列化

java对象序列化是将那些实现了Serializable接口的对象转换为一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象(反序列化)

1. 为什么需要序列化

一般创建的对象在程序关闭(JVM关闭)的时候,创建的对象就不会继续存在了;如果对象能够在程序不运行的情况下仍能存在并保存信息,那将非常有用;尽管可以通过保存到数据库或者存在文件来恢复对象;但是序列化可以将一个对象声明是“持久性”的,并为我们处理掉细节;(持久性意味着一个对象的生存周期并不取决于程序是否还在执行,它可以生存于程序的调用之间)

2. 序列化和反序列化的作用

2.1 Java的远程方法调用(RMI)

序列化和反序列化使得存活于其他计算机上的对象使用起来就像是存活于本地上一样;序列化和反序列化的过程可以通过网络进行:这意味着序列化机制能够自动弥补不同操作系统之间的差异;在window操作系统上序列化的对象可以linux操作系统上重新准确组装

当向远程对象放消息时,需要通过序列化来传输参数和返回值

2.2 对于java Beans来说,对象的序列化也是必须的;使用一个bean时,一般情况下是在设计阶段对它的状态信息进行配置。这种状态信息必须保存下来,并在程序启动时进行后期恢复。这种具体工作就是由对象序列化完成的。

3. 序列化和反序列化如何实现

3.1 序列化

要序列化一个对象,首先要创建某些OutputStream对象,然后将其封装在一个ObjectOutputStream对象内。这时,只需要调用OutputStream对象的writeObject()方法即可将对象序列化,并将其发送给OutputStream。

3.2 反序列化

要讲一个序列还原为一个对象,需要将一个InputStream封装在ObjectInputStream内,然后调用readObject();

[注]和往常一样,我们最后获得的是一个引用,它指向一个向上转型的Object,所以必须向下转型才能直接设置它们(用(ClassNname))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336523.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gluon_带有Gluon Ignite和Dagger的JavaFX中的依赖注入

gluon依赖注入抽象框架Gluon Ignite在几个流行的依赖注入框架(例如Spring,Dagger和Guice)上创建了一个通用抽象。 目前,Gluon 页面仅包含一个示例,该示例使用Gluon Ignite和Google Guice作为依赖注入框架,…

快速排序 自带时间复杂度检测

//时间复杂度 O(N*log2N //稳定性:不稳定 //来源于分治思想 /* 确定分界点 调整区间 递归处理两端算法思想,快排是基于冒泡排序的优化,冒泡排序从一侧开始进行,而快排是两边同时进行从而时间复杂度折半,同时包含了二…

java arraylist 常用方法_分享ArrayList中的几个常用方法的源码

jdk1.7.0_79上文里解析了有关ArrayList中的几个常用方法的源码——《有关ArrayList常用方法的源码解析》,本文将对LinkedList的常用方法做简要解析。LinkedList是基于链表实现的,也就是说它具备了链表的优点和缺点,随机访问慢、插入删除速度快…

java8 streams_Java 8 Streams API:对流进行分组和分区

java8 streams这篇文章展示了如何使用Streams API中可用的Collectors将具有groupingBy的流元素和具有partitioningBy的流元素进行groupingBy 。 考虑一系列Employee对象,每个对象都有名称,城市和销售数量,如下表所示: ---------…

【FFMPEG应用篇】使用FFMPEG解析H264编码为YUV格式

头文件 #pragma once#ifndef _VIDEO_DECODING_HEADER_ #define _VIDEO_DECODING_HEADER_#define INBUF_SIZE 4096 #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096extern "C" { #include "libavutil/opt.h" #include "libavcodec/…

java 反射api_Java学习笔记--反射API

反射API1.反射API的介绍通过反射API可以获取Java程序在运行时刻的内部结构。比如Java类中包含的构造方法、域和方法等元素,并可以与这些元素进行交换。按照 一般地面向对象的设计思路,一个对象的内部状态都应该通过相应的方法来改变,而不是直…

c++各类型有效范围

int -2147483648 ~ 2147483647 float 有6-7位有效数字 double 有15-16位有效数字

couchbase_具有Couchbase,Java EE和WildFly的CRUD Java应用程序

couchbaseCouchbase是一个开源的NoSQL文档数据库。 它允许访问,索引和查询JSON文档,同时利用集成的分布式缓存来实现高性能数据访问。 开发人员可以使用不同的语言(Java,Go,.NET,Node,PHP&…

java 对象的态_Java面向对象-------多态总结

1.多态:是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:多态性是对象多种表现形式的体现。2.多态作用:1. 消除类型之间的耦合关系2. 可替换性3. 可扩充性4…

C++ 【随想录】(六)C++后端向JS前端转换

需要包含的头文件 #include"comutil.h" #include"<string> BSTR转string BSTR bstrText ::SysAllocString(L"Test"); string str _com_util::ConvertBSTRToString(bstrText); SysFreeString(bstrText); string转BSTR…

netbeans连接数据库_NetBeans Java EE技巧#1 –数据库中的实体类

netbeans连接数据库NetBeans IDE是开发各种应用程序的绝佳选择。 具体来说&#xff0c;我每天都使用它来开发和维护Java EE应用程序。 在过去的几个发行版中&#xff0c;不仅Java EE的生产力提高了&#xff0c;而且NetBeans IDE还减少了开发应用程序的时间……使Java EE和NetBe…

java spring eventbus_spring集成guava的event bus

Guava的event busguava&#xff0c; https://github.com/google/guava 是一个非常有名的Java类库&#xff0c;提供了很多在日常开发中常用的集合、函数接口等。此外&#xff0c;guava还提供了一个模块叫做event bus&#xff0c;生产者往event bus上投递消息&#xff0c;event b…

LeetCode 66 加一

原题链接 关键词 &#xff1a;数组 模拟法 解题思路: 此题为处理数组&#xff0c;数组特点 --数组下标 可以前后覆盖 数组元素可交换等。 此题分为三种情况 1.传入数为234形式 &#xff0c;加一后无进位。直接在最后一个数组1即可 2.传入数为239形式&#xff0c;即…

jboss fuse 教程_使用JBoss Fuse和OpenShift进行Cloud Native Camel骑行

jboss fuse 教程红帽公司最近发布了一个微服务集成工具包&#xff0c;用于在OpenShift v3的Docker和Kubernetes环境中运行我们的微服务。 为了帮助人们更好地理解这一点&#xff0c;我将Rider Auto应用程序迁移到一组微服务中&#xff0c;该应用程序已经存在了一段时间&#xf…

java streamhandler_java中的Lamdba表达式和Stream

基于JDK 1.81、循环&#xff1a;// 以前的循环方式for (String player : players) {System.out.print(player "; ");}// 使用 lambda 表达式以及函数操作(functional operation)players.forEach((player) -> System.out.print(player "; "));// 在 Ja…

LeetCode 217 存在重复元素

原题链接 关键词 数组 排序 重复 解题思路 1.先把数组进行排序&#xff0c;然后比较是否有相邻的两个数字相等 ,有返回TRUE 无则返回FALSE 2.需要注意的是nums.size()-1 因为是从下标0开始&#xff0c;所以要-1&#xff0c;否则会造成数组越界 class Solution { pu…

java 代码运行速度慢_C代码的运行速度总是比Java快,对吧? 错误!

java 代码运行速度慢因此&#xff0c;我们都知道&#xff0c;Java解释缓慢且C的编译和优化运行速度非常快。 您可能知道&#xff0c;情况截然不同。 TL; DR Java适用于星座图&#xff0c;它的速度更快&#xff0c;在JIT上可以执行内联&#xff0c;因为所有方法/功能都是可见的…

LeetCode 26.删除排序数组中的重复项

原题 标签 &#xff1a; 数组 重复元素 有序 双指针 快慢指针 解题思路: 1.判断数组是否为空&#xff0c;为空返回0 2.我们可以放置两个指针 &#xff0c;其中 k 是慢指针&#xff0c;用来存下所有不同的数&#xff0c;而 j 是快指针用来扫描整个数组。只要 nums[i] n…

javaone_JavaOne 2015 –又一年,又向前迈进了一步

javaoneJavaOne 2015 San Francisco于10月25日至29日举行。 我很自豪地说这是我第九个人参加JavaOne&#xff0c;第七个人是演讲者&#xff0c;第四个人是Oracle员工&#xff0c;第三个人是内容委员会成员&#xff0c;第二个人是项目负责人。 我认为对于JavaOne来说&#xff0c…

lnp和mysql分开安装_毕业设计之LNP+DISCUZ +分离的数据库操作

环境介绍&#xff1a;CentOS6.9最小化安装https://nginx.org/download/nginx-1.16.1.tar.gzhttps://www.php.net/distributions/php-7.3.14.tar.gzhttps://cdn.mysql.com//Downloads/MySQL-5.7/mysql-boost-5.7.29.tar.gznginxphp主机&#xff1a;192.168.111.141mysql主机&…