Serializable java序列化
Bean Serializable Interface 的接口让BEAN可以串行化,将其变成一个可保存为以后使用的二进制流。当一个BEAN被系列化到磁盘上或者其他任何地方,其状态被保存起来,其中的属性 值也不会改变。在BEAN的规范中,JSP并没有要求BEAN实现Serializable接口。但是,如果您希望自己控制您所创建的组件的 serialization进程,或者您想serialize并不是标准组件扩展的组件,您必须了解serialization and deserialization的细节。
有几个原因你会把BEAN冷藏起来以备后用。有些服务器通过将所有的SESSION
数据(包括BEAN)写入磁盘来支持任意长的SESSION生命期,即使服务器停机也不会丢失。当服务器重新启动后,串行化的数据被恢复。同样的理由,在
重负载的站点上支持服务器分簇的环境中,许多服务器通过串行化来复制SESSION。如果你的BEAN不支持串行化,服务器就不能正确地保存和传输类。
通过同样的策略,你可以选择将BEAN保存在磁盘上或者数据库中,以备后用。例如,也许可以将客户的购物车实现为一个BEAN,在访问期间将其保存在数据库中。
如果BEAN需要特殊的复杂的初始设置,可以将BEAN设置好后串行化保存在磁盘上。这个BEAN的“快照”可以用在任何需要的地方,包括在$#@60;jsp:useBean$#@62;中用beanName属性的调用。
$#@60;jsp:useBean$#@62;标签中的beanName属性,用来实例化一个串行化的BEAN,而不是用来从一个类创建一个全新的实
例。如果BEAN还没有创建,beanName属性传给java.beans.Bean.instantiate()方法,由类装载器对类进行实例化。它
首先假定存在一个串行化的BEAN(带有扩展名.ser),然后会将其激活。如果这个操作失败,它就会实例化一个新的实例。
下面简单介绍一下这个接口:
对象能包含其它的对象,而这其它的对象又可以包含另外的对象。JAVA
serialization能够自动的处理嵌套的对象。对于一个对象的简单的域,writeObject()直接将值写入流。而,当遇到一个对象域
时,writeObject()被再次调用,如果这个对象内嵌另一个对象,那么,writeObject()
又被调用,直到对象能被直接写入流为止。程序员所需要做的是将对象传入ObjectOutputStream 的writeObject()
方法,剩下的将又系统自动完成。下面的例子创建了一个调用mine对象的PersonalData对象。代码实现的是将一个串和mine
对象输出到一个流,并存入一个文件:
public class PersonalData implements Serializable {
public int id
public int yearOfBirth;
public float yearlySalary;
}
PersonalData mine = new PersonalData(101, 1956, 46500.00);
FileOutputStream outstream = new FileOutputStream("PersonalData.ser");
ObjectOutputStream out = new ObjectOutputStream(outstream);
out.writeObject("My personal data"); //将一个串写入流
out.writeObject(mine); //将这个对象写入流
out.close(); // 清空并关闭流
...
一个FileOutputStream对象被创建且传到一个ObjectOutputStream。当out.writeObject()
被调用,这个串和mine 对象被objects are serializ顺序加入一个存入文件PersonalData.ser的字节对列。
您应该注意上述类是实现的java.io.Serializable接口。因为它并未指定要实现的方法,所以Serializable被称
为"tagging interface"
,但是它仅仅"tags"它自己的对象是一个特殊的类型。任一个您希望serialize的对象都应该实现这个接口。这是必须的。否则,用到流技术时将根
本不工作。例如,如果您试着去serialize 一个没有实现这个接口的对象,一个 NotSerializableException将产生。
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
Java的"对象序列化"能让你将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。
要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。这时,你就能用writeObject( )方法把对象写入OutputStream了。
writeObject 方法负责写入特定类的对象的状态,以便相应的 readObject 方法可以还原它。通过调用
out.defaultWriteObject 可以调用保存 Object
的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput
支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。
读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用readObject(
)方法。不过这样读出来的,只是一个Object的reference,因此在用之前,还得先下传。readObject
方法负责从流中读取并还原类字段。它可以调用 in.defaultReadObject 来调用默认机制,以还原对象的非静态和非瞬态字段。
defaultReadObject
方法使用流中的信息来分配流中通过当前对象中相应命名字段保存的对象的字段。这用于处理类发展后需要添加新字段的情形。该方法本身不需要涉及属于其超类或
子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入
ObjectOutputStream 来保存的。
看一个列子:








最后结果如下:
node 0
node 1
node 2
node 3
node 4
node 5
node 6
LiLy is 惠止南国
可以看到,在序列化的时候,writeObject与readObject之间的先后顺序。readObject将最先write的object read出来。用数据结构的术语来讲就姑且称之为先进先出吧!
在序列化时,有几点要注意的:
1:当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
2:如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
3:如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化
还有我们对某个对象进行序列化时候,往往对整个对象全部序列化了,比如说类里有些数据比较敏感,不希望序列化,一个方法可以用transient来标识,另一个方法我们可以在类里重写





这二个方法!
示例:



































--(add on 2006/6/28)
参考资料:JDK1.5 API DOC 孙鑫老师资料
1、实现Serializable回导致发布的API难以更改,并且使得package-private和private
这两个本来封装的较好的咚咚也不能得到保障了
2、Serializable会为每个类生成一个序列号,生成依据是类名、类实现的接口名、
public和protected方法,所以只要你一不小心改了一个已经publish的API,并且没有自
己定义一个long类型的叫做serialVersionUID的field,哪怕只是添加一个getXX,就会
让你读原来的序列化到文件中的东西读不出来(不知道为什么要把方法名算进去?)
3、不用构造函数用Serializable就可以构造对象,看起来不大合理,这被称为
extralinguistic mechanism,所以当实现Serializable时应该注意维持构造函数中所维
持的那些不变状态
4、增加了发布新版本的类时的测试负担
5、1.4版本后,JavaBeans的持久化采用基于XML的机制,不再需要Serializable
6、设计用来被继承的类时,尽量不实现Serializable,用来被继承的interface也不要
继承Serializable。但是如果父类不实现Serializable接口,子类很难实现它,特别是
对于父类没有可以访问的不含参数的构造函数的时候。所以,一旦你决定不实现
Serializable接口并且类被用来继承的时候记得提供一个无参数的构造函数
7、内部类还是不要实现Serializable好了,除非是static的,(偶也觉得内部类不适合
用来干这类活的)
8、使用一个自定义的序列化方法
看看下面这个保存一个双向链表的例子:
public class StringList implements Serializable
{
?private int size = 0;
?private Entry head = null;
?
?private static class Entry implements Serializable
?{
? String data;
? Entry next;
? Entry previous;
?}
?...//Remainder ommitted
}
这样会导致链表的每个元素以及元素之间的关系(双向链表之间的连接)
都保存下来,更好的方法是提供一个自定义的序列化如下:
//String List with a resonable custom serialized form
class StringList implements Serializable
{
? private transient int size = 0;?????? //!transient
? private transient Entry head = null;? //!transient
?
? //no longer serializable!
? private static class Entry
? {
??? String data;
??? Entry next;
??? Entry previous;
? }
?
? //Appends the specified string to the list
? public void add(String s) {/*...*/};
?
? /**
?? * Serialize this StringList
instance
?? * @author yuchifang
?? * @serialData The size of the list (the number of strings
* it contains) is emitted(int), in the proper sequence
?? */
? private void writeObject(ObjectOutputStream s)
throws IOException
? {
??? s.defaultWriteObject();
??? s.writeInt(size);
??? //Write out all elements in the proper order
??? for (Entry e = head; e != null; e = e.next)
????? s.writeObject(e.data);
? }
?
? private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
? {
??? int numElements = s.readInt();
???
??? //Read in all elements andd insert them in list
??? for (int i = 0; i < numElements; i++)
????? add((String)s.readObject());
? }
? //...remainder omitted
}
9、不管你选择什么序列化形式,声明一个显式的UID:
private static final long serialVersionUID = randomLongValue;
10、不需要序列化的东西使用transient注掉它吧,别什么都留着
11、writeObject/readObject重载以完成更好的序列化
readResolve 与 writeReplace重载以完成更好的维护invariant controllers
MarshalByRefObject和Serializable
最近在看web sevice 方面的东西,顺便看了下序列化,懂了不少啊 :
从MarshalByRefObject派生的类和有[Serializable]的类都可以跨越应用程序域作为参数传递。
从MarshalByRefObject派生的类按引用封送,有[Serializable]标志的类,按值封送。
如果此类即从MarshalByRefObject派生,也有[Serializable]标志也是按引用封送。
序列化有3种情况:
- 序列化为XML格式:
在webservice里,写个web method,传个自定义类做参数,就是这种情况。系统会帮你搞定,把自定义的类转换为默认XML格式。 - 序列化为2进制:
要加[Serializable]标志,可以把私有变量和公共变量都序列化。 - 序列化为soap格式:
需要实现ISerializable接口,定义序列化函数ISerializable.GetObjectData,和还原序列化的构造函数。
一个soap参数类的sample:


























是的,如果Session要存到数据库中就必须添加Serializable标记~
Serializable java序列化的更多相关文章
- java 序列化原来如此
上次面试的时候 ,如何实现java 类的序列化,当时感觉这个问题很简单,我的回答是实现serizlizable 接口就好了,可以实现对象的持久化,看了看书,原来这样: public class Ser ...
- Java 序列化Serializable详解
Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...
- 对Java Serializable(序列化)的理解和总结
我对Java Serializable(序列化)的理解和总结 博客分类: Java技术 JavaOSSocketCC++ 1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状 ...
- Java序列化与反序列化(Serializable)
Java序列化与反序列化(Serializable) 特别注意: 1.要序列化的类必须实现Serializable借口 2.在反序列化(读取对象)的时候必须额外捕获EOFException 3.序列化 ...
- Java Serializable(序列化)的理解和总结、具体实现过程(转)
原文地址:http://www.apkbus.com/forum.php?mod=viewthread&tid=13576&fromuid=3402 Java Serializable ...
- Java 序列化Serializable详解(附详细例子)
Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization ...
- Java序列化Serializable和Externalizable
纸上得来终觉浅,绝知此事要躬行 --陆游 问渠那得清如许,为有源头活水来 --朱熹 什么是Java序列化?为什么出现Java序列化?怎样实现Java序列化? 一.什么是Java序列化 ...
- Java序列化接口Serializable接口的作用总结
一.Java序列化接口Serializable的作用: 一个对象有对应的一些属性,把这个对象保存在硬盘上的过程叫做”持久化”. 对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字 ...
- 对Java Serializable(序列化)的理解和总结(一)
导读:最近在做项目的过程中,发现一个问题,就是我们最开始的时候,传递参数包括返回类型,都有map类型.但是由于map每次都要匹配key值,很麻烦.所以在之后就将参数传递和返回类型全都改成了实体bean ...
随机推荐
- CentOS 6.5通过yum安装和配置MySQL
0x00 说明 Linux安装MySQL一共有两种方式,一种是下载安装包离线安装,另一种就是通过yum在线安装,这里先介绍在线安装的方式,此方法简单方便,出错最少,但是无法控制安装的MySQL版本,如 ...
- SQL之DELETE
在SQL中DELETE语句用于删除表中的行. 语法 1.删除特定行 DELETE FROM 表名称 WHERE 列名称 = 值 2.删除所有行:在不删除表的情况下删除所有的行.删除之后表的结构.属性和 ...
- spark java API 实现二次排序
package com.spark.sort; import java.io.Serializable; import scala.math.Ordered; public class SecondS ...
- mysql 5.1 下载地址 百度云网盘下载
mysql 百度云下载 链接: https://pan.baidu.com/s/1fPSEcgtDN7aU2oQ_sL08Ww 提取码: 关注公众号[GitHubCN]回复2539获取
- deploy.sh
备份一下之前的一个脚本吧 #!bin/bash adb uninstall org.cocos2d.fishingjoy4 for apk in `find . -name '*.apk' | xar ...
- 基于CommonsChunkPlugin,webpack打包优化
前段时间一直在基于webpack进行前端资源包的瘦身.在项目中基于路由进行代码分离,http://www.cnblogs.com/legu/p/7251562.html.但是打包的文件还是很大,特别是 ...
- 集合栈计算机(UVa12096)
题目具体描述见:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_prob ...
- MVC 源码调试
源码调试,帮助你跟好理解MVC,使你开发跟牛B的程序. 1>在Visual命令行中运行“SN.EXE-Vr*,31BF3856AD364E35” 2. codeplex.com 上面找到,和你当 ...
- Deepin Linux安装MySQL方法
sudo apt-get install mysql-server apt-get install mysql-client sudo apt-get install libmysqlclient-d ...
- python: 模型的统计信息
/*! * * Twitter Bootstrap * */ /*! * Bootstrap v3.3.7 (http://getbootstrap.com) * Copyright 2011-201 ...