NewMoring

与Java同路,赢在未来。

统计

积分与排名

http://bbs.javawind.net/index.jspx

http://www.chubeibao.com/bbs/index.php

http://www.java2000.net/

http://www.javaeye.com/

http://www.javathinker.org/index.jsp

http://www.programbbs.com/bbs/index.asp

最新评论

java Serializable 类 序列化1《转帖》

1.5 定义类的可序列化域
可用两种不同的方式来定义类的可序列化域。类的可序列化域被缺省定义为非瞬态和非静态域。 通过在 Serializable 类中声明一个指定的域 serialPersistentFields,即可覆盖该缺省值。 该域的初始化必须用 ObjectStreamField 对象的数组来完成,该对象列出了可序列化域的名称和类型。该域的修饰符应为 private、static 和 final。
例如,以下声明将复制缺省行为。
class List implements Serializable {
    List next;
    private static final ObjectStreamField[] serialPersistentFields
                 = {new ObjectStreamField("next", List.class)};

}
用 serialPersistentFields 为某个类定义可序列化域后,即无需再将可序列化域限制在当前 Serializable 类的定义之内。利用第 1.7 节,"访问类的可序列化域" 中描述的接口,Serializable 类的 writeObject 和 readObject 方法可将该类的当前实现映射到其可序列化域。因此,后续版本中可以改变 Serializable 类的域,但前提是保持与版本兼容的 Serializable 域的映射。

1.6 对类的可序列化域和数据存档
对类的可序列化状态进行存档以使其与 Serializable 类的其它实现间可互操作,或者对类演变进行存档,这些都非常必要。对可序列化域进行存档可帮助用户最终确定该域是否应序列化。 序列化 javadoc 标记 @serial、@serialField 和 @serialData 可提供对源代码中 Serializable 类的序列化形式进行存档的方法。

对于缺省的可序列化域,@serial 标记应放在 javadoc 注释中。语法如下:@serial field-description 其中可选项 field-description 描述域及其容许值的含义。 field-description 可跨多行。当初始版本中增加一个域时,@since 标记指出所添域的版本。@serial 的 field-description 提供针对序列化的文档。在序列化形式文档内,field-description 将被添加到 javadoc 注释中。
@serialField 标记用于对 serialPersistentFields 数组的 ObjectStreamField 组件进行存档。每个 ObjectStreamField 组件都应使用其中的一个标记。语法如下:@serialField field-name field-type field-description
@serialData 标记描述写入或读取数据的次序和类型。该标记描述 writeObject 所写入的可选数据或 Externalizable.writeExternal 方法所写入的所有数据的次序或类型。语法如下:@serialData data-description
javadoc 应用程序识别序列化 javadoc 标记并为每个 Serializable 和 Externalizable 类生成说明文字。有关这些标记用法的示例,参见第 C.1 节 "java.io.File 可替代实现的示例。"

当某个类被声明为 Serializable 时,即通过可序列化域及可选数据(按名称和类型)定义了该对象的可序列化状态。可选数据只能用 Serializable 类中的 writeObject 方法显式写入,而其读取则可通过 Serializable 类和 readObject 方法进行。否则,序列化将跳过无法读取的可选数据。

当一个类被声明为 Externalizable 时,通过类自身写入流的数据即定义了该类的序列化状态。 该类必须指定顺序、类型及写入流的每个数据的含义。同时还必须处理其自身的演变,从而可读取以前版本所写入的数据,或写入以前版本所能读取的数据。在存储和恢复数据时,该类必须与父类相一致。必须指定流中父类数据的位置。

类的设计者必须确保为类存储的信息对于持久性是合适的,而且遵循为实现序列化的互操作性和演变而指定的序列化规则。第 5 章“可序列化对象的版本演变”对类的演变进行了更详细的说明。

1.10 Serializable 接口
Serialization 对象生成流,其中提供有关所存对象的 JavaTM 类的信息。对于可序列化对象,即使存在该类的不同(但兼容)版本的实现,也要保持足够的信息以恢复这些对象。定义 Serializable 接口可以标识实现可序列化协议的类:


package java.io;

public interface Serializable {};

Serializable 类必须具备如下功能:

实现 java.io.Serializable 接口
标识应序列化的域
(使用 serialPersistentFields 成员以显式声明其可序列化,或者使用瞬态关键字来指示非序列域。)
可访问其第一个非序列化父类的无参数构造函数。
该类可根据需要定义如下方法:

writeObject 方法,用于控制要保存哪些信息或将附加信息添加到流中
readObject 方法,用于读取由相应 writeObject 方法写入的信息,或在对象恢复后更新其状态
writeReplace 方法,用于允许类指定写入流的替换对象
readResolve 方法,用于允许类为刚从流中读取的对象指定替换对象
ObjectOutputStream 和 ObjectInputStream 支持所操作的可序列化类的演变(允许类发生改变以兼容早期版本的类)。有关实现兼容变化的机制的信息,参见第 5.5 节“兼容的 JavaTM 类型演变”。
--------------------------------------------------------------------------
class ObjectYouWannaSave implements Serializable{
   int x; int y;
   SubObject so = new SubObject();
   ..........
}

class SubObject implements Serializable{
   String s = "abc"; //String is OK, because String is java.io.Serializable
}

public class Save{ // in Save.java
   public void main(String[] args) {
      ObjectYouWannaSave original = new ObjectYouWannaSave();
      original.x = -1; original.y = 100; .....
     
      ObjectOutputStream out = null;
      try{
        out = new ObjectOutputStream(new FileOutputStream(new File("c:/save.dat")));
        out.writeObject(original);
      }catch(Exceptione){
      }finally{
        try{out.close();}catch(Exception e){}
      }
   }
}

public class Read{ // in Read.java
   public void main(String[] args) {
      ObjectInputStream in = null;
      try{
        out = new ObjectInStream(new FileInStream(new File("c:/save.dat")));
        ObjectYouWannaSave o = (ObjectYouWannaSave)in.readObject();
        System.out.println("x="+o.x);
        System.out.println("subobject.string=" + o.so.s);
        ........
      }catch(Exceptione){
      }finally{
        try{in.close();}catch(Exception e){}
      }
   }
}

这是个最简单的例子,先运行Save,以后什么时候运行Read都可以(只要c:\save.dat文件还存在就可以了)
--------------------------------------------------
对象的寿命通常随着生成该对象的程序终止而终止,有时候,可能需要将对象的状态保存下来,在需要的时候
再将对象恢复,我们把对象的这种记录自己状态的以便将来再生的能力,叫做对象的持续性(PERSISTENCE),
对象通过写出描述自己状态的数值来记录自己,这个过程叫对象的串行化Serializable。串行化的主要任务是写
出对象实例变量的值。如果变量是另一个对象的引用,则引用的对象也要串行化,这是个递归过程。
--------------------------------------------------------------------
java.io.Serializable interface是一个较为特殊的接口:
The serialization interface has no methods or fields and serves
only to identify the semantics of being serializable
即:它主要是一个用于通知JVM的标志

class X implements java.io.Serializable{...}

如果你要定制你自己的serializable行为,你应该在X中实现以下2个方法:
 private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

否则将按缺省的策略进行。

由于上述2个方法是private的,所以在某些情况下,可以使用
java.io.Serializable的子接口java.io.Externalizable,
在这个interface中有2个public方法:

public void writeExternal(ObjectOutput out)
                   throws IOException

public void readExternal(ObjectInput in)
                  throws IOException,
                         ClassNotFoundException


----------------------------------------------------------------------------
Serializable是一个串行化接口,它没有任何的属性和方法,一个类实现了串行化接口,就表明
该类具有持久性,通过WriteObjcet可将其持久保存在磁盘,在需要时,可用ReadObject从磁盘中读出,次时,对象的状态和存入似的相同。上面给出的列子比较简单,可通过串行化保存一个
链表对象,它的每个节点数据也会被保存。 当然,串行化接口还有其他用途,例如HTTP隧道等

-----------------------------------------------------------------------
对象序列化的持续性要和永久对象分别开。序列化只能达到有线持续性
在同一个jvm上可以重构对象的内容,达到持续性
---------------------------------------------------------------------
java序列化主要是用于两个方面:
一个是java的RMI(远程方法调用-Remote method invocation),你可以使用别人机器上的对象就像在你自己的机器上使用它一样(通过序列化),另外,在使用javabean时也需要使用序列化,序列化主要就是使用在这两方面。
-------------------------------------------------------------
所谓序列化就是把把对象以一个代码串的形式表示出来,
这样可以保存到磁盘或则通过网络传输,接受方可以在把代码串恢复成对象
具体的串形化方法可以自己写,接收放就可以根据您串形的规则把对象恢复出来
--------------------------------------------------------------------
序列化是把一个对象的状态写入一个字节流的过程,它执行RMI,RMI允许一台机器上的JAVA对象调用不同机器上的JAVA对象方法,对象可以作为参数提供给那个远程方法,发送机序列化该对象并传送它,接收机执行反序列化。
序列化和反序列化的关系图表可形成包含循环引用的顺序图表。这是整个序列化的总体思想。
而Serializable接口属于支持序列化的一个接口,只有一个实现它的对象可以被序列化工具存储和回复,Serializable接口没有定义任何成员,只用来表示一个累可以被序列化,若该类可以序列化,那么它的所有子类都可以。
下面是关于序列化的一个实例:
[b:a55efb5f91]程序名称:SerializationDemo.java
程序主题:实现对象的序列化和反序列化
程序说明:该程序由实例化一个MyClass类的对象开始,该对象有三个实例变量,类型分别为String、int、double,是希望存储和恢复的信息。[/b:a55efb5f91]

[code:1:a55efb5f91]

import java.io.*;

public class SerializationDemo{
        public static void main(String args[]){

//Object serialization
try{
MyClass object1=new MyClass("Hello",-7,2.7e10);
System.out.println("object1:"+object1);
FileOutputStream fos=new FileOutputStream("serial");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(object1);
oos.flush();
oos.close();
}
catch(Exception e){
System.out.println("Exception during serialization:"+e);
System.exit(0);
}

//Object deserialization
try{
MyClass object2;
FileInputStream fis=new FileInputStream("serial");
ObjectInputStream ois=new ObjectInputStream(fis);
object2=(MyClass)ois.readObject();
ois.close();
System.out.println("object2:"+object2);
}
catch(Exception e){
System.out.println("Exception during deserialization:"+e);
System.exit(0);
}
}
}

class MyClass implements Serializable{
String s;
int i;
double d;
public MyClass(String s,int i,double d){
this.s=s;
this.i=i;
this.d=d;
}
public String toString(){
return "s="+s+";i="+i+";d="+d;
}
}
[/code:1:a55efb5f91]

程序运行结果:object1和object2的实例变量是一样的,输出如下:[code:1:a55efb5f91]object1:s=Hello;i=-7;d=2.7E10
object2:s=Hello;i=-7;d=2.7E10[/code:1:a55efb5f91]
--------------------------------------------------------------------------------
Object serialization的定义:
Object serialization 允许你将实现了Serializable接口的对象转换为字节序列,这些字节序列可以被完全存储以备以后重新生成原来的对象。 

serialization不但可以在本机做,而且可以经由网络操作(就是猫小说的RMI)。这个好处是很大的----因为它自动屏蔽了操作系统的差异,字节顺序(用Unix下的c开发过网络编程的人应该知道这个概念,我就容易在这上面犯错)等。比如,在Window平台生成一个对象并序列化之,然后通过网络传到一台Unix机器上,然后可以在这台Unix机器上正确地重构这个对象。


Object serialization主要用来支持2种主要的特性:
1。Java的RMI(remote method invocation).RMI允许象在本机上一样操作远程机器上的对象。当发送消息给远程对象时,就需要用到serializaiton机制来发送参数和接收返回直。

2。Java的JavaBeans.   Bean的状态信息通常是在设计时配置的。Bean的状态信息必须被存起来,以便当程序运行时能恢复这些状态信息。这也需要serializaiton机制。

 

二。持久化
持久化应该是英文里的persistence.但是Java语言里现在只支持lightweight persistence,就是轻量级持久化,这是通过serialization机制来实现的。

persistence是指一个对象的生命周期不由程序是否执行来决定,即使是在程序终止时这个对象也存在。它把一个serializable的对象写到磁盘(本机或其他机器上的非RAM存储器),并在程序重新调用时再读取对象到通常的RAM存储器。

为什么说Java的serialization机制实现的是lightweight persistence?因为你必须显式的序列化和反序列化程序里的对象;而不是直接由一个关键词来定义一个对象是序列化的然后由系统做相应的处理。  如果以后的Java版本出现一个新的关键字来实现这种机制,比如就是persistence,如果我用

persistence  (String s="chinaunix")

然后系统自动做上面程序里的那些处理,那么Java就实现了persistence.

posted on 2009-05-27 14:16 清晨 阅读(749) 评论(0)  编辑  收藏 所属分类: java语言的相关问题


只有注册用户登录后才能发表评论。


网站导航: