J2SE中的序列化之接受默认序列化

2016-02-19 12:30 1 1 收藏

关注图老师设计创意栏目可以让大家能更好的了解电脑,知道有关于电脑的更多有趣教程,今天给大家分享J2SE中的序列化之接受默认序列化教程,希望对大家能有一点小小的帮助。

【 tulaoshi.com - 编程语言 】


  首先要了解Java默认的序列化行为,java将一切关于对象的信息都保存了下了,也就是说,有些时候那些不需要保存的也被保存了下来。一般情况下,我们仅仅需要保存逻辑数据就可以了。不需要保存的数据我们可以用要害字transient标出。
  
  以下是一个例子:
  
  import java.io.*;
  
  public class Serial implements Serializable {
  
   int company_id;
  
   String company_addr;
  
   transient boolean company_flag;
  
  }
  
  则company_flag字段将不会参与序列化与反序列化,但同时你也增加了为他初始值的责任。这也是序列化经常导致的问题之一。因为序列化相当于一个只接受数据流的public构造函数,这种对象构造方法是语言之外的。但他仍然是一种形式上的构造函数。如若你的类不能够通过其他方面来保证初始化,则你需要额外的提供readObject方法,首先正常的反序列化,然后对transient标示的字段进行初始化。
  
  在不适合的时候,使用java默认的序列化行为可能会带来速度上的影响,最糟糕的情况是,可能导致溢出。在某些数据结构的实现中,经常会充斥着各种的循环引用,而java的默认序列化行为,并不了解你的对象结构,其结果就是java试图通过一种昂贵的“图遍历”来保存对象状态。可想而知,不但慢而且可能溢出。这时候你就要提供自己的readObject,来代替默认的行为。
  
  兼容性问题
  
  兼容性历来是复杂而麻烦的问题。
  
  不要兼容性:
  
  首先来看看假如我们的目的是不要兼容性,应该注重哪些。不要兼容性的场合很多,比如war3每当版本升级就不能够读取以前的replays。
  
  兼容也就是版本控制,java通过一个名为UID(stream unique identifier)来控制,这个UID是隐式的,它通过类名,方法名等诸多因素经过计算而得,理论上是一一映射的关系,也就是唯一的。假如UID不一样的话,就无法实现反序列化了,并且将会得到InvalidClassException。
  
  当我们要人为的产生一个新的版本(实现并没有改动),而抛弃以前的版本的话,可以通过显式的声名UID来实现:
  
  private static final long serialVersionUID=****; 你可以编造一个版本号,但注重不要重复。这样在反序列化的时候老版本将得到InvalidClassException,我们可以在老版本的地方捕捉这个异常,并提示用户升级的新的版本。
  
  当改动不大时,保持兼容性(向下兼容性的一个特例):
  
  有时候你的类增加了一些无关紧要的非私有方法,而逻辑字段并不改变的时候,你当然希望老版本和新版本保持兼容性,方法同样是通过显式的声名UID来实现。下面我们验证一下。
  
  老版本:
  
  import java.io.*;
  
  public class Serial implements Serializable {
  
   int company_id;
  
   String company_addr;
  
   public Serial1(int company_id, String company_addr) {
  
  this.company_id = company_id;
  
  this.company_addr = company_addr;
  
   }
  
   public String toString() {
  
  return "DATA: "+company_id+" "+
  
  company_addr;
  
   }
  
  }新版本
  
  import java.io.*;
  
  public class Serial implements Serializable {
  
   int company_id;
  
   String company_addr;
  
   public Serial1(int company_id, String company_addr) {
  
  this.company_id = company_id;
  
  this.company_addr = company_addr;
  
   }
  
   public String toString() {
  
  return "DATA: "+company_id+" "+ company_addr;
  
   }
  
   public void todo(){}//无关紧要的方法
  
  } 首先将老版本序列化,然后用新版本读出,发生错误:
  
  java.io.InvalidClassException: Serial.Serial1; local class incompatible: stream classdesc serialVersionUID = 762508508425139227, local class serialVersionUID = 1187169935661445676 接下来我们加入显式的声名UID:
  
  private static final long serialVersionUID=762508508425139227l; 再次运行,顺利地产生新对象
  
  DATA: 1001 com1
  
  如何保持向上兼容性:
  
  向上兼容性是指老的版本能够读取新的版本序列化的数据流。经常出现在我们的服务器的数据更新了,仍然希望老的客户端能够支持反序列化新的数据流,直到其更新到新的版本。可以说,这是半自动的事情。
  

来源:https://www.tulaoshi.com/n/20160219/1601077.html

延伸阅读
标签: Web开发
PHP不支持永久对象,在OOP中永久对象是可以在多个应用的引用中保持状态和功能的对象,这意味着拥有将对象保存到一个文件或数据库中的能力,而且可以在以后装入对象。这就是所谓的序列化机制。PHP 拥有序列化方法,它可以通过对象进行调用,序列化方法可以返回对象的字符串表示。然而,序列化只保存了对象的成员数据而不包话方法。 在PHP4中...
标签: PHP
本文转自:http://www.coolcode.cn/?p=170 1.前言 PHP (从 PHP 3.05 开始)为保存对象提供了一组序列化和反序列化的函数:serialize、unserialize。不过在 PHP 手册中对这两个函数的说明仅限于如何使用,而对序列化结果的格式却没做任何说明。因此,这对在其他语言中实现 PHP 方式的序列化来说,就比较麻烦了。虽然以前也搜集...
标签: PHP
串行化大概就是把一些变量转化成为字符串的字节流的形式,这样比较容易传输、存储。当然,关是传输存储没有什么,关键是变成串的形式以后还能够转化回来,而且能够保持原来数据的结构。 在PHP中有多串行化处理的函数:serialize(),该函数把任何变量值(除了资源变量)转化为字符串的形式,可以把字符串保存到文件里,或...
假设有一下一个实体类。 using System; using System.Xml; using System.Xml.Serialization; namespace TestPerson { public class Person { public string FullName; [NonSerialized()] public string Password; public Male sex; } public enum Male { M, F } } 先决定用xml 序列化把对象的状态dump到一个xml文件。 代...
在很多应用中我们需要对数据进行保存,或是从介质上读取数据,这就涉及到文件的操作。我们可以利用各种文件存取方法完成这些工作,但MFC中也提供了一种读写文件的简单方法——“序列化”。序列化机制通过更高层次的接口功能向开发者提供了更利于使用和透明于字节流的文件操纵方法,举一个例来讲你可以将一个字串写入文件而不需要理会具体长度,...

经验教程

806

收藏

78
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部