Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1086229
  • 博文数量: 121
  • 博客积分: 10085
  • 博客等级: 上将
  • 技术积分: 3415
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-18 10:48
文章分类

全部博文(121)

文章存档

2013年(1)

2012年(2)

2011年(2)

2010年(10)

2009年(43)

2008年(63)

我的朋友

分类: Java

2008-07-04 16:17:57

一、    关于serialVersionUID:

1.             通常要声明一个序列化版本号,诸如: "private static final long      

serialVersionUID = 7526472295622776147L; "

2.             在新的版本中不更改serialVersionUID的值,如果更改将会引起与旧序列化对象的不兼容.

3.             新的序列化类是否可以读出老的序列化对象取决于所作更改的性质.

 

二、关于不兼容的更改:

1.         对类中某个变量或方法的删除:这样会便得老序列化版本的类在读新序  

列化版本的对象时会把一些新版本的值设为默认值来,这样做反而会削弱老版本完成反序列化的能力.

2.         将类的层次颠倒:这样会便得数据在数据流中的序列错误.

3.         更改非静态的field为静态的.或将nontransient 改为transient:对于默认生成的序列化,这种做法等同于删除这个field.这样做这个数据将不会被写入数据流中.当删除一个field的时候,老序列化版本将会初始化一个默认的值,这样会引起不可想象的错误.

4.         更改原来field的数据类型:

5.         更改readObject或者writeObject,以使得它不再能读或写默认的field,或者更改它们去读/写原来版本中不可以读/写的.

6.         将可序列化类改为Externalizable,反之亦然.

7.         non-enum类改为enum.

8.         Serializabe或者Externalizabe去掉.

9.         增加一些可以产生新对象的writeReplace或者readResolve方法.

 

三、关于readObject writeObject:

1.         实现readObjectwriteObject的方法必须首先调默认方法.

2.         readObject方法必须在Serializable类中实现,在反序列化结束后进行反序列化对象的检验.

3.         static transient域是不会进行默认的序列化的.

 

四、需要注意的几点:

1.     内部类尽可能少地被序列化.

2.     容器类应该经常以Hashtable 形式出现而不是大的哈希表数据结构.Hashtable这种形式通过K,V对的存储来实现序列化.

3.     对象能包含其它的对象,而这其它的对象又可以包含另外的对象。JAVA serialization能够自动的处理嵌套的对象。对于一个对象的简单的域,writeObject()直接将值写入流。而,当遇到一个对象域时,writeObject()被再次调用,如果这个对象内嵌另一个对象,那么,writeObject() 又被调用,直到对象能被直接写入流为止。程序员所需要做的是将对象传入ObjectOutputStream writeObject() 方法,剩下的将又系统自动完成。

4.     实现Serializable回导致发布的API难以更改,并且使得package-privateprivate
这两个本来封装的较好的咚咚也不能得到保障了

5.     Serializable会为每个类生成一个序列号,生成依据是类名、类实现的接口名、
public
protected方法,所以只要你一不小心改了一个已经publishAPI,并且没有自己定义一个long类型的叫做serialVersionUIDfield,哪怕只是添加一个getXX,就会让你读原来的序列化到文件中的东西读不出.

6.     不用构造函数用Serializable就可以构造对象,看起来不大合理,这被称为
extralinguistic mechanism
,所以当实现Serializable时应该注意维持构造函数中所维

持的那些不变状态

7.     设计用来被继承的类时,尽量不实现Serializable,用来被继承的interface也不要
继承Serializable。但是如果父类不实现Serializable接口,子类很难实现它,特别是

对于父类没有可以访问的不含参数的构造函数的时候。所以,一旦你决定不实现

Serializable
接口并且类被用来继承的时候记得提供一个无参数的构造函数.

8.     不管你选择什么序列化形式,声明一个显式的UID
private static final long serialVersionUID = randomLongValue;

 

关于嵌套类序列化的一个例子:

import java.io. * ;

class tree implements java.io.Serializable {
public tree left;
public tree right;
public int id;
public int level;

private static int count = 0 ;

public tree( int depth) {
id = count ++ ;
level = depth;
if (depth > 0 ) {
left = new tree(depth - 1 );
right = new tree(depth - 1 );
}
}

public void print( int levels) {
for ( int i = 0 ; i < level; i ++ )
System.out.print( " " );
System.out.println( " node " + id);

if (level <= levels && left != null )
left.print(levels);

if (level <= levels && right != null )
right.print(levels);
}


public static void main (String argv[]) {

try {
/**/ /*
创建一个文件写入序列化树。
*/
FileOutputStream ostream = new FileOutputStream( " tree.tmp " );
/**/ /*
创建输出流
*/
ObjectOutputStream p = new ObjectOutputStream(ostream);

/**/ /*
创建一个二层的树。
*/
tree base = new tree( 2 );

p.writeObject(base); //
将树写入流中。

p.writeObject( " LiLy is
惠止南国
" );
p.flush();
ostream.close(); //
关闭文件。


/**/ /*
打开文件并设置成从中读取对象。
*/
FileInputStream istream = new FileInputStream( " tree.tmp " );
ObjectInputStream q = new ObjectInputStream(istream);

/**/ /*
读取树对象,以及所有子树
*/
tree new_tree = (tree)q.readObject();

new_tree.print( 2 ); //
打印出树形结构的最上面 2级

String name = (String)q.readObject();
System.out.println( " \n " + name);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}


  最后结果如下:


node 0
node 1
node 2
node 3
node 4
node 5
node 6

LiLy is
惠止南国


  可以看到,在序列化的时候,writeObjectreadObject之间的先后顺序。readObject将最先writeobject read出来。用数据结构的术语来讲就姑且称之为先进先出吧!


  在序列化时,有几点要注意的:

  1:当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。

  2:如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。

  3:如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个SerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化

 

 

 

______________________________________________________________

 

以上有的是在网上找的资料,有的是自己译的.有不对的地方还请指教.

阅读(1518) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~