首先声明,我是一个菜鸟。一下文章中出现技术误导情况盖不负责
序列化就是一种用来处置对象流的机制,所谓对象流也就是将对象的内容停止流化,将数据分解成字节流,以便存储在文件中或在网络上传输。可以对流化后的对象停止读写操纵,也可将流化后的对象传输于网络之间。序列化是为了处理在对对象流停止读写操纵时所激发的问题。 序列化的实现:将须要被序列化的类实现Serializable接口,该接口没有须要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后应用一个输出流(如:FileOutputStream)来结构一个ObjectOutputStream(对象流)对象,接着,应用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流;
序列化分为两大部分:序列化和反序列化。序列化是这个进程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例
序列化的什么特点:
如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。
什么时候应用序列化:
一:对象序列化可以实现分布式对象。重要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。
二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以停止对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能失掉整个对象序列。
======================
可以看看接口java.io.serializable的中文解释:
Serializable
public interface Serializable
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的全部子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
要允许不可序列化类的子类型序列化,可以假定该子类型负责保存和还原超类型的公用 (public)、受保护的 (protected) 和(如果可访问)包 (package) 字段的状态。仅在子类型扩展的类有一个可访问的无参数结构方法来初始化该类的状态时,才可以假定子类型有此义务。如果不是这种情况,则声明一个类为可序列化类是错误的。该错误将在运行时检测到。
在反序列化进程中,将应用该类的公用或受保护的无参数结构方法初始化不可序列化类的字段。可序列化的子类必须能够访问无参数的结构方法。可序列化子类的字段将从该流中还原。
当遍历一个图形时,可能会遇到不支持可序列化接口的对象。在此情况下,将抛出 NotSerializableException,并将标识不可序列化对象的类。
在序列化和反序列化进程中须要特殊处置的类必须应用下列精确签名来实现特殊方法:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
writeObject 方法负责写入特定类的对象的状态,以便响应的 readObject 方法可以还原它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字段的默许机制。该方法本身不须要触及属于其超类或子类的状态。状态是通过应用 writeObject 方法或应用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。
readObject 方法负责从流中读取并还原类字段。它可以调用 in.defaultReadObject 来调用默许机制,以还原对象的非静态和非瞬态字段。defaultReadObject 方法应用流中的信息来分配流中通过以后对象中响应命名字段保存的对象的字段。这用于处置类开展后须要添加新字段的情况。该方法本身不须要触及属于其超类或子类的状态。状态是通过应用 writeObject 方法或应用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。
将对象写入流时须要指定要应用的替换对象的可序列化类,应应用精确的签名来实现此特殊方法:
ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
此 writeReplace 方法将由序列化调用,前提是如果此方法存在,而且它可以通过被序列化对象的类中定义的一个方法访问。因此,该方法可以拥有私有 (private)、受保护的 (protected) 和包私有 (package-private) 访问。子类对此方法的访问遵循 java 访问规矩。
在从流中读取类的一个实例时须要指定替换的类应应用的精确签名来实现此特殊方法。
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
此 readResolve 方法遵循与 writeReplace 相同的调用规矩和访问规矩。
序列化运行时应用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化进程中用于验证序列化对象的发送者和接收者是不是为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会致使 InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、终究 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面盘算该类的默许 serialVersionUID 值,如“Java(TM) 对象序列化标准”中所述。不过,强烈建议 全部可序列化类都显式声明 serialVersionUID 值,原因盘算默许的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化进程中可能会致使意外的 InvalidClassException。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议应用 private 修改器表现声明 serialVersionUID(如果可能),原因是这种声明仅应用于当即声明类 -- serialVersionUID 字段作为继承成员没有用处。
java.io.Serializable激发的问题——什么是序列化?在什么情况下将类序列化?
序列化就是一种用来处置对象流的机制,所谓对象流也就是将对象的内容停止流化。可以对流化后的对象停止读写操纵,也可将流化后的对象传输于网络之间。序列化是为了处理在对对象流停止读写操纵时所激发的问题。序列化的实现:将须要被序列化的类实现Serializable接口,该接口没有须要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后应用一个输出流(如:FileOutputStream)来结构一个ObjectOutputStream(对象流)对象,接着,应用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
序列化:序列化是将对象转换为轻易传输的格式的进程。例如,可以序列化一个对象,然后应用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流从新结构对象。
是对象永久化的一种机制。
确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消逝,但如果我们想把某些对象(因为是对象,所以有各自不同的特性)保存上去,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存上去的对象。这种情况下就要用到对象的序列化。
只有序列化的对象才可以存储在存储设备上。为了对象的序列化而须要继承的接口也只是一个象征性的接口而已,也就是说继承这个接口说明这个对象可以被序列化了,没有其他的目标。之所以须要对象序列化,是因为有时候对象须要在网络上传输,传输的时候须要这种序列化处置,从服务器硬盘上把序列化的对象取出,然后通过网络传到客户端,再由客户端把序列化的对象读入内存,执行响应的处置。
对象序列化是java的一个特征,通过该特征可以将对象写作一组字节码,当在其他位置读到这些字节码时,可以依此创立一个新的对象,而且新对象的状态与原对象完整相同。为了实现对象序列化,要求必须能够访问类的私有变量,从而保证对象状态能够准确的得以保存和恢复。响应的,对象序列化API能够在对象重建时,将这些值还原给私有的数据成员。这是对java语言访问权限的挑战。通常用在服务器客户端的对象交换上面,另外就是在本机的存储。
对象序列化的最重要的用处就是在传递,和保存对象(object)的时候,保证对象的完整性和可传递性。譬如通过网络传输,或者把一个对象保存成一个文件的时候,要实现序列化接口 。
*
Quote:
比拟java.io.Externalizable和java.io.Serializable
http://www.zdnet.com.cn/developer/code/story/0,3800066897,39304080,00.htm
即使你没有用过对象序列化(serialization),你可能也晓得它。但你是不是晓得 Java 还支持另外一种情势的对象持久化,外部化(externalization)?
上面是序列化和外部化在代码级的关联方式:
public interface Serializable {}
public interface Externalizable extends Serializable {
void readExternal(ObjectInput in);
void writeExternal(ObjectOutput out);
}
序列化和外部化的重要区别
外部化和序列化是实现统一目标的两种不同方法。上面让我们分析一下序列化和外部化之间的重要区别。
通过Serializable接口对对象序列化的支持是内建于核心 API 的,但是java.io.Externalizable的全部实现者必须供给读取和写出的实现。Java 已具有了对序列化的内建支持,也就是说只要制作自己的类java.io.Serializable,Java 就会试图存储和重组你的对象。如果应用外部化,你就可以选择完整由自己实现读取和写出的工作,Java 对外部化所供给的独一支持是接口:
voidreadExternal(ObjectInput in)
void writeExternal(ObjectOutput out)
现在如何实现readExternal() 和writeExternal() 就完整看你自己了。
序列化会自动存储必要的信息,用以反序列化被存储的实例,而外部化则只保存被存储的类的标识。当你通过java.io.Serializable接口序列化一个对象时,有关类的信息,比如它的属性和这些属性的类型,都与实例数据一同被存储起来。在选择走Externalizable这条路时,Java 只存储有关每个被存储类型的非常少的信息。
每个接口的优点和缺点
Serializable接口
· 优点:内建支持
· 优点:易于实现
· 缺点:占用空间过大
· 缺点:由于额外的开销致使速度变比拟慢
Externalizable接口
· 优点:开销较少(程序员决定存储什么)
· 优点:可能的速度晋升
· 缺点:虚拟机不供给任何帮助,也就是说全部的工作都落到了开发人员的肩上。
在两者之间如何选择要根据应用程序的需求来定。Serializable通常是最简单的处理方案,但是它可能会致使出现不可接受的性能问题或空间问题;在出现这些问题的情况下,Externalizable可能是一条可行之路。
要记住一点,如果一个类是可外部化的(Externalizable),那么Externalizable方法将被用于序列化类的实例,即使这个类型供给了Serializable方法:
private void writeObject()
private void readObject()
文章结束给大家分享下程序员的一些笑话语录:
问答
Q:你是怎么区分一个内向的程序员和一个外向的程序员的? A:外向的程序员会看着你的鞋和你说话时。
Q:为什么程序员不能区分万圣节和圣诞节? A:这是因为 Oct 31 == Dec 25!(八进制的 31==十进制的 25)
---------------------------------
原创文章 By
序列化和对象
---------------------------------