java中的序列化问题

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,将数据分解成字节流,以便存储在文件中或在网络上传输。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。 序列化的实现:将需要被序列化的类实现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()

时间: 2024-10-11 10:13:00

java中的序列化问题的相关文章

Java中如何序列化一个对象(转)

转自:http://blog.csdn.net/chx10051413/article/details/40784667 http://www.cnblogs.com/baoendemao/p/3804797.html Java 中如何序列化一个对象 我们都知道java 中无法保存一个对象到文本文件中,但是当我们有这种需求的时候,我们可以通过java 的序列化功能把当前对象的一些属性以二进制的形式保存到文件中.当我们需要这个对象的时,只需要从二进制文件中还原为保存前的对象即可.从这里我们可以得到

面试题:Java中对象序列化接口(Serializable)的意义

Serializable接口是一个里面什么都没有的接口 它的源代码是public interface Serializable{},即什么都没有. 如果一个接口里面什么内容都没有,那么这个接口是一个标识接口,比如,一个学生遇到一个问题,排错排了几天也没解决,此时,她举手了(示意我去帮他解决),然后我过去,帮他解决了,那么这个举手其实就是一个标识,自己不能解决的问题标示我去帮他解决,在Java中的这个Serializable接口是给JVM看的,告诉JVM,我不做这个类的序列化了,你(JVM)给我序

java中的序列化与反序列化,还包括将多个对象序列化到一个文件中

package Serialize; /** * Created by hu on 2015/11/7. *///实现序列化必须实现的接口,这就是一个空接口,起到标识的作用import java.io.Serializable; /** * 用来进行序列化和反序列化的类 * */public class person implements Serializable { private int age; private String name; private String sex; public

Java中的序列化

以下内容引用自http://wiki.jikexueyuan.com/project/java/serialization.html: Java提供了一种机制,叫做对象序列化,这里对象被描述成一系列包括对象的数据以及有关对象的类型和在对象中存储的数据的类型的字节. 在一个序列化的对象被写进文件之后,它能在文件中被读出并被反序列化为类型信息和表示对象的字节,并且它的数据可以被用来重新创建在内存中的对象. 最让人印象深刻的是整个过程是JVM独立的,意味着一个对象能在一个平台上序列化,并能在在一个完全

java中的序列化和反序列化学习笔记

需要序列化的Person类: package cn.itcast_07; import java.io.Serializable; /* * NotSerializableException:未序列化异常 * * 类通过实现 java.io.Serializable 接口以启用其序列化功能.未实现此接口的类将无法使其任何状态序列化或反序列化. * 该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口. * * java.io.InvalidClassException: * cn.it

在Java中进行序列化和反序列化

对象序列化的目标是将对象保存在磁盘中,或者允许在网络中直接传输对象. 对象序列化允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久保存在磁盘上或者通过网络将这种二进制流传输到另外一个网络节点. 其他程序一旦获得了这种二进制流,都可以将这种二进制流恢复成原本的Java对象. 序列化的含义和意义 序列化机制允许将实现序列化的Java对象转换成字节序列,这些字节序列可以进行持久化或者通过网络传输,使得对象可以脱离程序的运行而独立存在. 序列化将一个Java对象写入IO流中.

java中的序列化流和反序列化流

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px SimSun; color: #4e9072 } 序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输.  对象 -- 流数据(ObjectOutputStream) 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象.流数据 -- 对象(ObjectInputStream) 序列化流和反序列化流不同于字节流 字符流 内存字节流,这些都是把字符串写入/读取文件,序列

Java中实现序列化的两种方式 Serializable 接口和 Externalizable接口

方法一: 实现Serializable接口,这个我就不多说了 方法二: 实现Externalizable接口: 例子: package demo; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; public class XXS implements Externalizable{ private String n

[转]java 中的序列化是什么意思?有什么好处?

1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保存Object States,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化. 2.什么情况下需要序列化 a)当你想把的内存中的对象保存到一个文件中或者数据库中时候: b)当你想用套接字在网络上传送对象的时候: c)当你想通过RMI传输对象的时候: 3.当对一个对象实现序列化时,究竟发生了什么? 在没有序列化前,每个保存在堆(Hea