Java Serializable(序列化)的理解和总结、具体实现过程(转)
原文地址:http://www.apkbus.com/forum.php?mod=viewthread&tid=13576&fromuid=3402
Java Serializable(序列化)的理解和总结、具体实现过程
内存中的对象是怎么存在的? 内存中各种对象的状态是? 实例变量是什么(指的是实例化的对象吗)? 使用序列化的好处是什么?
1、序列化是干什么的?
简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保
存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
2、什么情况下需要序列化
a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;
3、当对一个对象实现序列化时,究竟发生了什么?
在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如:
Java代码
1. Foo myFoo = new Foo();
2. myFoo .setWidth(37);
3. myFoo.setHeight(70);
当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.dat文件中,这样以后又可以
把它
从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对
象。
Java代码
1. FileOutputStream fs = new FileOutputStream("foo.dat");
2. ObjectOutputStream os = new ObjectOutputStream(fs);
3. os.writeObject(myFoo);
4、实现序列化(保存到一个文件)的步骤
a)Make a FileOutputStream
Java代码
1. FileOutputStream fs = new FileOutputStream("foo.ser");
b)Make a ObjectOutputStream
Java代码
1. ObjectOutputStream os = new ObjectOutputStream(fs);
c)write the object
Java代码
1. os.writeObject(myObject1);
d) close the ObjectOutputStream
Java代码
1. os.close();
5、举例说明
Java代码
1. import java.io.*;
4. public class Box implements Serializable
5. {
6. private int width;
7. private int height;
8.
9. public void setWidth(int width){
10. this.width = width;
11. }
12. public void setHeight(int height){
13. this.height = height;
14. }
15.
16. public static void main(String[] args){
17. Box myBox = new Box();
18. myBox.setWidth(50);
19. myBox.setHeight(30);
20.
21. try{
22. FileOutputStream fs = new FileOutputStream("foo.ser");
23. ObjectOutputStream os = new ObjectOutputStream(fs);
24. os.writeObject(myBox);
25. os.close();
26. }catch(Exception ex){
27. ex.printStackTrace();
28. }
29. }
30.
31. }
6、相关注意事项
a)序列化时,只对对象的状态进行保存,而不管对象的方法;
b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
d)并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如:
1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。
序列化是什么:
序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。
序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便
存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例
序列化的什么特点:
如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。
什么时候使用序列化:
一:对象序列化可以实现分布式对象。主要应用例如:rmi要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。
二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络
连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
类通过实现java.io.serializable接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
要允许不可序列化类的子类型序列化,可以假定该子类型负责保存和还原超类型的公用(public)、受保护的(protected)和(如果可访问)
包(package)字段的状态。仅在子类型扩展的类有一个可访问的无参数构造方法来初始化该类的状态时,才可以假定子类型有此责任。如果不是这种情况,
则声明一个类为可序列化类是错误的。该错误将在运行时检测到。
在反序列化过程中,将使用该类的公用或受保护的无参数构造方法初始化不可序列化类的字段。可序列化的子类必须能够访问无参数的构造方法。可序列化子类的字段将从该流中还原。
当遍历一个图形时,可能会遇到不支持可序列化接口的对象。在此情况下,将抛出notserializableexception,并将标识不可序列化对象的类。
在序列化和反序列化过程中需要特殊处理的类必须使用下列准确签名来实现特殊方法:
writeobject方法负责写入特定类的对象的状态,以便相应的readobject方法可以还原它。通过调用
out.defaultwriteobject可以调用保存object的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用
writeobject方法或使用dataoutput支持的用于基本数据类型的方法将各个字段写入objectoutputstream来保存的。
readobject方法负责从流中读取并还原类字段。它可以调用in.defaultreadobject来调用默认机制,以还原对象的非静态和非
瞬态字段。defaultreadobject方法使用流中的信息来分配流中通过当前对象中相应命名字段保存的对象的字段。这用于处理类发展后需要添加新
字段的情形。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用writeobject方法或使用dataoutput支持的用于基本数据类型
的方法将各个字段写入objectoutputstream来保存的。
将对象写入流时需要指定要使用的替代对象的可序列化类,应使用准确的签名来实现此特殊方法:
此writereplace方法将由序列化调用,前提是如果此方法存在,而且它可以通过被序列化对象的类中定义的一个方法访问。因此,该方法可以拥有
私有(private)、受保护的(protected)和包私有(package-private)访问。子类对此方法的访问遵循java访问规则。
在从流中读取类的一个实例时需要指定替代的类应使用的准确签名来实现此特殊方法。
序列化运行时使用一个称为serialversionuid的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和
接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的serialversionuid与对应的发送者的类的版本号不同,则反序列化
将会导致invalidclassexception。可序列化类可以通过声明名为"serialversionuid"的字段(该字段必须是静态
(static)、最终(final)的long型字段)显式声明其自己的serialversionuid:
如果可序列化类未显式声明serialversionuid,则序列化运行时将基于该类的各个方面计算该类的默认serialversionuid值,如“
java(tm)对象序列化规范”中所述。不过,强烈建议所有可序列化类都显式声明serialversionuid值,原因计算默认的
serialversionuid对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的
invalidclassexception。因此,为保证serialversionuid值跨不同java编译器实现的一致性,序列化类必须声明一个
明确的serialversionuid值。还强烈建议使用private修改器显示声明serialversionuid(如果可能),原因是这种声明
仅应用于立即声明类--serialversionuid字段作为继承成员没有用处。
java.io.serializable引发的问题——什么是序列化?在什么情况下将类序列化?
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。
序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现serializable接口,该接口没有需要实现的方
法,implementsserializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:fileoutputstream)来构
造一个objectoutputstream(对象流)对象,接着,使用objectoutputstream对象的
writeobject(objectobj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
序列化:序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用http通过internet在客户端和
服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。
是对象永久化的一种机制。
确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失,但如果我们想把某些对象(因为是对象,所以有各自不同
的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存下来的对象。这种情况下就
要用到对象的序列化。
只有序列化的对象才可以
服务器硬盘上把序列化的对象取出,然后通过网络传到客户端,再由客户端把序列化的对象读入内存,执行相应的处理。
对象序列化是java的一个特征,通过该特征可以将对象写作一组字节码,当在其他位置读到这些字节码时,可以依此创建一个新的对象,而且新对象的状态
与原对象完全相同。为了实现对象序列化,要求必须能够访问类的私有变量,从而保证对象状态能够正确的得以保存和恢复。相应的,对象序列化api能够在对象
重建时,将这些值还原给私有的数据成员。这是对java语言访问权限的挑战。通常用在服务器客户端的对象
交换上面,另外就是在本机的存储。
对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整性和可传递性。譬如通过网络传输,或者把一个对象保存成一个文件的时候,要实现序列化接口。
即使你没有用过对象序列化(serialization),你可能也知道它。但你是否知道
java还支持另外一种形式的对象持久化,外部化(externalization)?
下面是序列化和外部化在代码级的关联方式:
序列化和外部化的主要区别
外部化和序列化是实现同一目标的两种不同方法。下面让我们分析一下序列化和外部化之间的主要区别。
通过serializable接口对对象序列化的支持是内建于核心api的,但是java.io.externalizable的所有实现者必须提供
读取和写出的实现。java已经具有了对序列化的内建支持,也就是说只要制作自己的类java.io.serializable,java就会试图存储和
重组你的对象。如果使用外部化,你就可以选择完全由自己完成读取和写出的工作,java对外部化所提供的唯一支持是接口:
序列化会自动存储必要的信息,用以反序列化被存储的实例,而外部化则只保存被存储的类的标识。当你通过java.io.serializable接口
序列化一个对象时,有关类的信息,比如它的属性和这些属性的类型,都与实例数据一起被存储起来。在选择走externalizable这条路时,java
只存储有关每个被存储类型的非常少的信息。
每个接口的优点和缺点
JAVA•优点:内建支持
•优点:易于实现
•缺点:占用空间过大
•缺点:由于额外的开销导致速度变比较慢
•优点:开销较少(程序员决定存储什么)
•优点:可能的速度提升
•缺点:虚拟机不提供任何帮助,也就是说所有的工作都落到了开发人员的肩上。
在两者之间如何选择要根据应用程序的需求来定。serializable通常是最简单的解决方案,但是它可能会导致出现不可接受的性能问题或空间问题;在出现这些问题的情况下,externalizable可能是一条可行之路。
要记住一点,如果一个类是可外部化的(externalizable),那么externalizable方法将被用于序列化类的实例,即使这个类型提供了serializable方法:
Java Serializable(序列化)的理解和总结、具体实现过程(转)的更多相关文章
- [Java] Serializable(序列化)的理解
1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保存object st ...
- java对象序列化的理解
1.java中的序列化时transient变量(这个关键字的作用就是告知JAVA我不可以被序列化)和静态变量不会被序列 化(下面是一个测试的例子) (实体带versionUUID,便 ...
- 对Java Serializable(序列化)的理解和总结(二)
遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化 b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化 c,ser ...
- Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释
遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题a,什么叫序列化和反序列化b,作用.为啥要实现这个 Serializable 接口,也就是为啥要序列化c,seria ...
- [转]Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释
原文地址:https://blog.csdn.net/qq_27093465/article/details/78544505 遇到这个 Java Serializable 序列化这个接口,我们可能会 ...
- java之序列化
详细内容 连接https://blog.csdn.net/qq_27093465/article/details/78544505 Java 之 Serializable 序列化和反序列化的概念,作用 ...
- 对Java Serializable(序列化)的理解和总结
我对Java Serializable(序列化)的理解和总结 博客分类: Java技术 JavaOSSocketCC++ 1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状 ...
- Java Serializable(序列化)的理解和总结
1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保存object st ...
- 理解Java对象序列化(二)
关于Java序列化的文章早已是汗牛充栋了,本文是对我个人过往学习,理解及应用Java序列化的一个总结.此文内容涉及Java序列化的基本原理,以及多种方法对序列化形式进行定制.在撰写本文时,既参考了Th ...
随机推荐
- Qt 二进制文件读写(使用“魔术数字”)
今天开始进入 Qt 的另一个部分:文件读写,也就是 IO.文件读写在很多应用程序中都是需要的.Qt 通过 QIODevice 提供了IO的抽象,这种设备(device)具有读写字节块的能力.常用的IO ...
- Silverlight之OOB模式下的一些事
本文简介: 1.为什么要使用OOB?使用OOB的作用? 2.如何实现OOB模式 3.对OOB进行一些设置: 4.检测OOB的安装状态: 5.更新应用程序: 6.WebBrowser控件: 7.桌面通知 ...
- (转)CSS+DIV float 定位
来自:http://www.cnblogs.com/iyangyuan/archive/2013/03/27/2983813.html 很早以前就接触过CSS,但对于浮动始终非常迷惑,可能是自身理解能 ...
- android SharedPreferences 使用
除了SQLite数据库外,SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值 对数据,通常用来存储一些简单的配置信息.其存储位置在/dat ...
- git删除中文文件
git中出现如下代码时,是因为文件中包含中文.而且我们也无法用 git rm name 命令来删除该文件. deleted: "chrome_plugin/source_file/iHub\ ...
- 彻底搞懂javascript中的match, exec的区别
在工作中经常发现一些同学把这两个方法搞混,以致把自己弄的很郁闷.所以我和大家一起来探讨一下这两个方法的奥妙之处吧. 我们分以下几点来讲解: 相同点: 1.两个方法都是查找符合条件的匹配项,并以数组形式 ...
- VBSCRIPT事件绑定(隐式)
很多新版的浏览器都开始不支持VBSCRIPT 所以系统开始不断地有script错误,开始比较多地接触VBSCRIPT vbscript 和javascript 事件绑定的类似方法为 vbscript: ...
- apache开源项目--Camel
Apache Camel 是一个非常强大的基于规则的路由以及媒介引擎,该引擎提供了一个基于POJO的 企业应用模式(Enterprise Integration Patterns)的实现,你可以采用其 ...
- MenuInflater用法
MenuInflater是用来加载menu布局文件的. 与LayoutInflater类似,应用程序运行时会预先加载资源中的布局文件,如果Menu布局中的资源比较多,会影响性能,所以可以选择MenuI ...
- html语意化标签
一.布局的理解误区 网络上流行管新型的布局方式叫“DIV+CSS”,其实是一个错误的理解,导致了很多人过度依赖 与滥用DIV标签, HTML提供了我们一共七八十个标签,其中常用的有三十个左右,DIV不 ...