`

深入浅出java 序列化概念

阅读更多
  在做继承时,Eclipse经常会报The serializable class *** does not declare a static final serialVersionUID field of type long这个警告,今天我就从网上载录了这部分说明.方便自己记忆,也方便大家参考.
  序列化是什么:
  序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。
  序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例
  序列化的什么特点:
  如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。
  什么时候使用序列化:
  一:对象序列化可以实现分布式对象。主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。
  二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
    序列化javadoc中的解释
  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()

分享到:
评论

相关推荐

    深入浅出Java语言程序设计

    "深入浅出Java语言程序设计"是一本旨在帮助读者全面理解Java编程精髓的书籍。以下将根据标题和描述,深入探讨Java语言的核心概念和关键特性。 1. **Java简介**:Java是由Sun Microsystems开发的,后来被Oracle公司...

    计算机软件-编程源码-深入浅出Java语言程序设计.zip

    《深入浅出Java语言程序设计》是一本专为学习和理解Java编程语言而设计的教材。这本书涵盖了从基础到高级的Java编程概念,旨在帮助读者深入理解Java的各个方面,从而能够熟练地进行软件开发。 首先,Java语言是面向...

    head first java 深入浅出java pdf版

    7. **I/O流**:学习输入/输出流的概念,包括文件读写、对象序列化和网络数据传输。 8. **多线程**:理解并发编程,如何创建和管理线程,以及同步和互斥的概念。 9. **接口与抽象类**:区分接口和抽象类的区别,...

    深入浅出gRPC-李林峰.zip

    《深入浅出gRPC》是李林峰撰写的一本关于gRPC框架的详细教程,旨在帮助读者全面理解和掌握这一先进的远程过程调用(RPC)框架。gRPC是Google开源的一个高性能、开源和通用的RPC框架,它基于HTTP/2协议标准,采用...

    关于Java对象序列化您不知道的5件事Java开发Java

    Java对象序列化是Java开发中的一个重要概念,它允许我们将Java对象转换为字节流,以便存储、传输或在不同时间点恢复。以下是五个可能不为人知的关于Java对象序列化的知识点,这些知识点对于深入理解Java开发至关重要...

    Head First_深入浅出Java(中文第2版)_带书签_高清完整版 4980

    《Head First 深入浅出Java》是美国作家Kathy Sierra和Bert Bates共同编著的一本经典Java编程教材,特别适合初学者和有一定经验的程序员用来深入理解Java语言。这本书以其独特的“Head First”学习风格而闻名,强调...

    序列化(三) 实例分析深入了解序列化

    在Java编程语言中,序列化是一个关键的概念,它允许对象的状态被转换为字节流,以便存储、传输或恢复。序列化是许多高级功能的基础,如持久化、网络通信和分布式计算。这篇博客“序列化(三) 实例分析深入了解序列化...

    深入浅出hibernate,需要的下载

    通过《深入浅出Hibernate》这本书,你可以系统地学习这些概念,并掌握如何在实际项目中应用Hibernate,提升数据库操作的效率和代码的可维护性。书中的实例和解释将帮助你更好地理解和实践这些知识点。

    『新鲜出炉,深入浅出java百度云(csdn)————程序.pdf

    以上只是Java面试中常见的一些知识点,实际上涵盖的范围更广泛,包括设计模式、网络编程、数据库连接池、缓存技术、序列化等。对于Java开发者来说,不断学习和深入理解这些概念是提升专业技能的关键。

    深入浅出netty-3.rar

    《深入浅出Netty》是针对Java网络编程框架Netty的一份详细讲解文档,由阿里巴巴的专家编写。Netty是一个高性能、异步事件驱动的网络应用程序框架,它为开发可维护的高性能协议服务器和客户端提供了丰富的组件和API。...

    Java 的对象永续之道

    侯捷的文章深入浅出地介绍了Java中对象持久化的基本原理和技术实现,对于理解面向对象编程中的重要概念具有很高的参考价值。序列化不仅是一项实用的技术,也是理解和设计软件系统的关键组成部分之一。随着技术的进步...

    深入浅出Hibernate

    ### 深入浅出Hibernate #### ORM概念与原则 ORM(Object Relational Mapping,对象关系映射)是一种编程技术,用于将面向对象语言中的对象映射到关系型数据库中的记录上。它允许开发人员使用面向对象的方式进行...

    深入浅出Google+Android

    《深入浅出Google+Android》是一本专门为Android开发新手量身打造的教程,旨在帮助读者从零基础开始,逐步掌握Android应用开发的核心技术。书中的内容涵盖了Google与Android的紧密关系,以及如何利用Google的相关...

Global site tag (gtag.js) - Google Analytics