问题:
OOP 编程中, 有时候需要将整个对象及其状态保存起来,放到一个永久性的存储空间里,在需要时还可以将该对象还原成原来的状态,即使通过网络传递到不同的操作系统的计算机上也可以运行。这种将程序中的对象写入文件,之后的某个时候再从文件中把对象恢复出来的机制就是所谓的对象序列化。对象序列化是非常有意义的事情,它可以把实现分布式对象处理,如远程方法调用( RMI ),就是利用对象序列化机制实现运行远程主机上的服务如同在本地机上运行该对象一样的效果。这个过程的实质就是把对象作为远程参数由发送方将其序列化以后发送出去,由接收方通过反序列化操作恢复该对象,然后提供给需要该对象的方法使用。
反序列化时, JAVA 虚拟机用头信息生成对象实例,然后将对象字节流中的数据复制到对象数据成员中,最后,如果不想序列化对象中的某些成员。可以把他们修饰成 transient ,
解决思路:
查看 JDK 文档, Serializable 并没有定义任何成员,只是简单地指示一个类是否可以被序列化,因此该接口仅仅被用作一种标记,用来通知 JVM 需要将这个类的对象进行序列化。此外如果一个类是可序列化的,那么它的所有子类也是可序列化的。
序列化的实现用到对象流类: ObjectInputStream 和 ObjectOutputStream ,他们可以实现针对对象的几乎所有的成员变量的保存和读取操作。
包含对象的字节流在传送过程中并不传送类的字节码,而只是传输类名和签名。也就是说 readObject() 在收到对象时,需要 JVM 装入指定的类文件,若找不到相应的类文件就会报错: ClassNotFoundException() 。如果需要传输对象数据和字节码,解决的方法就是 RMI 框架。
序列化只能保存对象的非静态成员变量,不能保存任何方法,构造函数和静态成员变量,而且序列化保存的只是变量的值,对于变量的任何修饰符,都不能保存。这样一来,序列化的过程会将 private 型的数据也保存下来,引发安全问题,这时的解决办法是将其标志为 transient 。这样就不会保存了。
并非所一的类都可以实现序列化,具体序列化哪个对象必须在程序中明确指出,而不是交给系统自动识别。由于有些类的对象所表示的数据在不断地变化,所以他们不能被序列化,例如: java.io.FileInputStream 、 java.lang.Thread 等如果某个可序列化对象包含某个不可序列化对象的引用,那么整个序列化都会失败,而且抛出 NotSerializableException 异常。
如果作为一个可以被序列化的对象中的某个成员变量仍然是个对象,而且这个对象是可序列化的,那么这个成员变量同样可被序列化。经常遇到这种情况,被序列化的对象包含了到其它对象的引用,而这些对象又引用了其它的对象,甚至是自己,这样形成了一张对象网,如果希望序列化一个在对象网顶点的对象时,所有它引用的对象都将被递归地实现序列化并别写到文件中。当一次序列化过程中序列化多个对象时,他们中相同的内容将会被以共享的方式写入。
序列化技术可提供对两种主要特性的支持。一种是远程方法调用(
RMI
)
,
它在将消息发送给远程对象时,提供对象序列化传递参数和返回值,这样使得本来存在于其它机器上的对象表现出好像就在本机上的行为。另一种特性就是
javabean,
可以认为对象序列化是
javabean
所必须的。因为使用一个
bean
时,它的状态信息通常在设计期间配置好。程序启动以后这种状态信息必须保存下来,以便程序启动以后恢复,而这些由序列化来实现。
注意:
1、
一个对象拥有
private
成员,在序列化过程中是不受保护的,需要将其修饰为
transient
;
2、
对于那些不能实现
serializable
接口的对象,是不能执行序列化操作的,这些对象状态往往总是变化的,所有序列化也没有意义。
3、
序列化不仅能保存对象的全景图,而且能追踪对象内包含的所有所有引用并保存那些对象,接着又能对美国对象内部包含的引用进行追踪,形成对象网,单个对象可与之建立连接,而且还包含了对象的引用数组及成员对象。
下面的例子演示如何序列化一张对象网以及反序列化后在对某个对象进行修改时所造成的影响:
例子:
Student类:
主要代码:
private static final long serialVersionUID = 5550994935417493896L;
public Student( long id, String name, int age, String department) {
super ();
this . id = id;
this . name = name;
this . age = age;
this . department = department;
}
public String toString() {
return "[ 学号 ]" + id + "[ 姓名 ]" + name + "[ 年龄 ]" + age + "[ 院系 ]" + department ;
}
public class SerielizableDemo {
public static void main(String a[]) throws IOException, ClassNotFoundException{
Student s1;
Student s2;
s1 = new Student(200, "Tom" , 18, "info" );
s2 = new Student(300, "Lisa" , 88, "math" );
System. out .println( "status before object is serialized." );
System. out .println(s1);
System. out .println(s2);
// 创建文件输出流,保存文件的状态
FileOutputStream fos = new FileOutputStream( "data.dat" );
ObjectOutputStream oos = new ObjectOutputStream(fos);
System. out .println( "object is serialized and save to file..." );
oos.writeObject(s1);
oos.writeObject(s2);
oos.close();
Student new1,new2;
FileInputStream fis = new FileInputStream( "data.dat" );
ObjectInputStream ois = new ObjectInputStream(fis);
new1 = (Student) ois.readObject ();
new2 = (Student) ois.readObject ();
ois.close();
System. out .println( "object is recovered from the file..." );
System. out .println(new1);
System. out .println(new2);
}
}
例子:
public class Logon implements Serializable {
private static final long serialVersionUID = -7983416206310404876L;
private String name ;
private transient String password ;
Logon(String name, String password) {
this . name = name;
this . password = password;
}
public String toString(){
String pwd = ( null == password ) ? "(null)" : password ;
return "logon info:" + "\n[username: ]" + name + "\n[password: ]" + pwd;
}
}
public class SendLogon {
public static void main(String args[]) throws FileNotFoundException, IOException{
Logon a = new Logon( "David" , "123" );
System. out .println(a);
ObjectOutputStream oos = new ObjectOutputStream( new
FileOutputStream( "logon.out" ));
System. out .println ( "Sending object of logn..." );
oos.writeObject(a);
oos.close();
}
}
public class AcceptLogon {
public static void main (String a[]) throws FileNotFoundException, IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream( new
FileInputStream( "Logon.out" ));
Logon b = (Logon) ois .readObject();
ois .close();
System. out .println(b);
}
}
例子:
Employee 类的主要代码
public void raiseSalary( double byPercent){
double raise = salary * byPercent /100;
salary += raise;
}
public String toString (){
return getClass().getName() + "[" + name + ",salary=" + salary + "]" ;
}
Manager 主要代码:
public void setSecretary(Employee secretary) {
this . secretary = secretary;
}
public String toString (){
return super .toString() + "[secretary=" + secretary + "]" ;
}
public class SerObjectDemo {
public static void main(String args[]){
new Employee( "David" , 1);
new Manager( "Lisa" , 3);
manager.setSecretary (emp);
Employee[] staff = new Employee[2];
staff[0] = emp;
staff[1] = manager;
try {
ObjectOutputStream oos = new ObjectOutputStream( new
FileOutputStream( "emp.dat" ));
oos.writeObject(staff);
oos.close();
ObjectInputStream ois = new ObjectInputStream( new
FileInputStream( "emp.dat" ));
Employee[]
发表评论
-
深入分析 Java 中的中文编码问题
2011-11-16 07:45 0几种常见的编码格式 ... -
Java 编码
2011-11-16 07:44 0http://zhidao.baidu.com/quest ... -
java字符编码原理解析
2011-11-16 07:43 0可以理解为计算机没 ... -
HttpClient
2011-11-03 11:07 836From http://www.blogjava.net/Al ... -
ECLIPSE ANT OutOfMemoryError
2011-08-04 17:23 1018ANT BUILD MEMORY ERROR: [cl ... -
JDBC BATCH
2011-07-05 14:58 0PreparedStatement ps = conn.pre ... -
OUT OF MEMORY WHEN BUILD
2011-02-22 17:47 01, ANT BUILD: In Eclipse op ... -
spring weblogic jndi
2011-02-16 09:18 1844weblogic:weblogic8.1 数据库:MySql ... -
log4j 邮件
2011-01-24 15:54 0<!-- 设置上下文参数 --> ... -
tomcat weblogic
2010-12-01 11:25 1868EJB 层基本搞定,以前测试 EJB 也都是写一个 appli ... -
ant weblogic “local class incompatible: stream classdesc serialVersionUI”
2010-11-29 12:41 2239weblogic.management.Management ... -
Debugging with the Maven Jetty Plugin in Eclipse
2010-11-15 17:42 1043debug: http://docs.codehaus.or ... -
maven tomcat eclipse debug
2010-11-15 17:36 1956from: http://bandaidprogrammin ... -
maven app tomcat 部署
2010-11-11 15:56 1312修改pom.xml,添加如下配置: <build ... -
Maven Cargo Tomcat 部署
2010-11-11 15:49 1774pom.xml中<build>下添加如下代码: ... -
java中读取配置文件各种方法
2010-09-07 12:31 01。使用Java.util.Properties类的load( ... -
ThreadGroup
2010-05-25 08:47 0在Java中每个线程都属于某个线程组(ThreadGroup) ... -
java Excel 导出
2010-03-28 20:06 0public void createExcel(OutputS ... -
java小数保留两位小数
2009-11-19 16:49 2341方式一: 四舍五入 double f = ... -
java中实现xml schema 验证文件
2009-11-16 20:05 3884XML 是可扩展标记语言,也就是说其中的标记我们可以按照我们 ...
相关推荐
Xson是一个Java对象序列化和反序列化程序。支持Java对象到字节数组的序列化,和从字节数组到Java对象的反序列化。 Maven: <groupId>com.github.xsonorg</groupId> <artifactId>xson-core <version>1.0.1 ...
### Java对象序列化标准知识点详解 #### 一、系统架构概览 **1.1 概览** Java 对象序列化是一种将Java对象的状态转换成字节流的过程,以便于在网络上传输或存储到磁盘上。Java序列化标准定义了一套规则来描述如何...
### C#对象序列化与反序列化 #### 1. 对象序列化的介绍 ##### (1).NET支持对象序列化的几种方式 .NET框架提供了多种序列化机制,它们各自有不同的应用场景和特点。 - **二进制序列化**: - **定义**:二进制...
Java对象序列化是Java平台的一项重要特性,它允许将对象的状态转换为字节流,以便存储、传输或恢复。在本文中,我们将深入探讨关于Java对象序列化你可能不知道的五件事情,这些知识点对于理解和优化你的Java应用程序...
Java对象序列化是一种将Java对象转换为字节流的过程,以便可以存储在磁盘上、在网络上传输或在任何其他需要持久化数据的场景中使用。这个过程涉及到两个主要概念:序列化(Marshalling)和反序列化(Unmarshalling)...
Java对象序列化是一种将Java对象转换为字节流的过程,以便可以存储这些对象或通过网络进行传输。这个过程是Java平台的核心特性,它允许开发者将复杂的对象结构持久化或者在网络间进行安全通信。序列化不仅可以用于...
【JAVA对象序列化保存为XML文件的工具类】 在Java编程中,对象序列化是一种将对象的状态转换为字节流的过程,以便可以存储或在网络上传输。而在反序列化时,这个字节流又可以恢复为原来的对象。Java提供了一个方便...
本主题将深入探讨如何在Windows Forms(WF)环境中,利用C#语言进行对象的直接保存与读取,以及通过对象序列化和反序列化的方式实现对象的保存与恢复。 首先,我们来理解什么是对象的直接保存与读取。在C#中,可以...
序列化的过程就是对象写入字节流和从字节流中读取对象。...对象序列化功能非常简单、强大,在RMI、Socket、JMS、EJB都有应用。对象序列化问题在网络编程中并不是最激动人心的课题,但却相当重要,具有许多实用意义。
对象序列化和反序列化流
Java对象序列化是一种将对象转换为字节流的过程,以便可以将其存储在磁盘上,或者在网络中进行传输。这是Java平台提供的一种功能,允许程序员将任何Java对象持久化,即将其状态保存到磁盘,或者在网络中进行传输。...
在IT领域,对象序列化是一项重要的技术,它允许将复杂的数据结构转化为字节流,以便于存储或传输。本文将详细讲解如何在VS(Visual Studio)和VC++环境中实现对象序列化,并将其保存到SQLite数据库的blob(Binary ...
Java对象序列化与反序列化是Java编程中重要的概念,主要应用于数据持久化、网络传输以及存储等场景。本文将详细解析这两个概念及其在实际应用中的实现方式。 **一、Java对象序列化** 1. **定义**: Java对象序列化...
在Android开发中,对象序列化是一种重要的技术,它允许我们将对象的状态转化为可存储或可传输的数据格式,便于在不同进程间传递或者持久化保存。在标题"android 对象序列化"中,我们要讨论的是如何在Android环境中...
### Java基础:对象序列化深度解析 #### 序列化概述与目标 对象序列化是Java编程语言中的一项核心功能,旨在将对象的状态转换为字节流,以便于存储或在网络上传输。这一过程通常涉及将对象转换为二进制格式,以便...
提出了一种基于JSON的对象序列化算法,该算法通过分析JSON文法并建立对象导航图,透明地将Java对象序列化成JSON表达式,使客户端能够很好地利用JavaScript引擎来解析JSON响应,有效地解决了解析XML所造成的缺陷。
在.NET框架中,C#对象序列化是一种将对象的状态转换为可存储或可传输的数据格式的过程。这在很多场景下非常有用,例如保存用户会话、传输数据到远程服务器或者持久化对象到数据库。对象序列化的概念是核心的编程概念...
将Java对象序列化成ISO-8859-1、Base64字节流和Xml字符串三种方式。
XStream对象序列化是一种在Java应用程序中将Java对象转换为XML格式的过程,这主要通过XStream库实现。这个库提供了一种简洁的方式来处理对象到XML的转换,反之亦然,而不需要复杂的配置或对对象进行特定的修改。...
对象序列化是软件开发中一个重要的概念,尤其是在分布式系统和跨平台数据交换中。在.NET框架中,对象的序列化是通过System.Xml.Serialization命名空间来实现的,这使得开发者能够将对象转换为XML格式的数据,方便...