惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Vulnerabilities – Threatpost
Cloudbric
Cloudbric
G
GRAHAM CLULEY
S
Securelist
Schneier on Security
Schneier on Security
Help Net Security
Help Net Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Project Zero
Project Zero
Spread Privacy
Spread Privacy
P
Privacy International News Feed
C
Cyber Attacks, Cyber Crime and Cyber Security
Cisco Talos Blog
Cisco Talos Blog
T
Tailwind CSS Blog
博客园_首页
有赞技术团队
有赞技术团队
Simon Willison's Weblog
Simon Willison's Weblog
Stack Overflow Blog
Stack Overflow Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Latest news
Latest news
T
Tor Project blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Attack and Defense Labs
Attack and Defense Labs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
O
OpenAI News
J
Java Code Geeks
T
Tenable Blog
K
Kaspersky official blog
AWS News Blog
AWS News Blog
S
Security @ Cisco Blogs
The GitHub Blog
The GitHub Blog
T
Threatpost
月光博客
月光博客
H
Heimdal Security Blog
Security Latest
Security Latest
The Hacker News
The Hacker News
Y
Y Combinator Blog
A
Arctic Wolf
Apple Machine Learning Research
Apple Machine Learning Research
C
Cisco Blogs
美团技术团队
Microsoft Security Blog
Microsoft Security Blog
Hugging Face - Blog
Hugging Face - Blog
T
The Blog of Author Tim Ferriss
C
CERT Recently Published Vulnerability Notes
D
Docker
Google Online Security Blog
Google Online Security Blog
D
DataBreaches.Net
V
Visual Studio Blog
H
Help Net Security

博客园 - jascha

Eclipse可视化基面设计方法 Eclipse RCP的解释 java学习步骤 JAVA中的开源框架 Javascript键盘响应及空格屏蔽 - jascha - 博客园 给Eclipse换个启动界面! Eclipse安装AJAX环境(ATF,DOJO,Extjs...) Eclipse快捷键 yui-ext~~~cool! 部署Tomcat环境 捣鼓Mashup Mashup,老调新唱~ 微软的新技术 久违,重逢 对网格技术应用的分析 比较集群、网格、P2P区别(表格阐释) ASP.NET AJAX调用WS步骤 我的博客列表 开张大吉啦!
干嘛要序列化?
jascha · 2007-06-13 · via 博客园 - jascha

序列化定义:

  • 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,就使得数据能够被轻松地存储和传输。
  • 持久化,最本质,webservice传送对象,还是remoting,还是cache等等,都是把对象可以保存起来再使用。
  • 简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的!

         比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化{ A a = new A(); B b = new B(); },这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!

以下序列化机制的解决方案:

    1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)

    2.当要保存一个对象时,先检查该对象是否被保存了。

    3.如果以前保存过,只需写入"与已经保存的具有序列号x的对象相同"的标记,否则,保存该对象

    通过以上的步骤序列化机制解决了对象引用的问题!

序列化的实现

    将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

修改默认的序列化机制 

在序列化的过程中,有些数据字段我们不想将其序列化,对于此类字段我们只需要在定义时给它加上transient关键字即可,对于transient字段序列化机制会跳过不会将其写入文件,当然也不可被恢复。但有时我们想将某一字段序列化,但它在SDK中的定义却是不可序列化的类型,这样的话我们也必须把他标注为transient,可是不能写入又怎么恢复呢?好在序列化机制为包含这种特殊问题的类提供了如下的方法定义:

private void readObject(ObjectInputStream in) throws

IOException, ClassNotFoundException;

private void writeObject(ObjectOutputStream out) throws

IOException;

(注:这些方法定义时必须是私有的,因为不需要你显示调用,序列化机制会自动调用的)

使用以上方法我们可以手动对那些你又想序列化又不可以被序列化的数据字段进行写出和读入操作。

下面是一个典型的例子,java.awt.geom包中的Point2D.Double类就是不可序列化的,因为该类没有实现Serializable接口,在我的例子中将把它当作LabeledPoint类中的一个数据字段,并演示如何将其序列化!

import java.io.*;

import java.awt.geom.*;

public class TransientTest

{

public static void main(String[] args)

{

LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00);

try

{

System.out.println(label);//写入前

ObjectOutputStream out = new ObjectOutputStream(new

FileOutputStream("Label.txt"));

out.writeObject(label);

out.close();

System.out.println(label);//写入后

ObjectInputStream in = new ObjectInputStream(new

FileInputStream("Label.txt"));

LabeledPoint label1 = (LabeledPoint)in.readObject();

in.close();

System.out.println(label1);//读出并加1.0后

}

catch (Exception e)

{

e.printStackTrace();

}

}

class LabeledPoint implements Serializable

{

public LabeledPoint(String str, double x, double y)

{

label = str;

point = new Point2D.Double(x, y);

}

private void writeObject(ObjectOutputStream out) throws IOException

{

/**

*必须通过调用defaultWriteObject()方法来写入

*对象的描述以及那些可以被序列化的字段

*/

out.defaultWriteObject();

out.writeDouble(point.getX());

out.writeDouble(point.getY());

}

private void readObject(ObjectInputStream in)

throws IOException, ClassNotFoundException

{

/**

*必须调用defaultReadObject()方法

*/

in.defaultReadObject();

double x = in.readDouble() + 1.0;

double y = in.readDouble() + 1.0;

point = new Point2D.Double(x, y);

}

{

return getClass().getName()

+ "[label = "+ label

+ ", point.getX() = "+ point.getX()

+ ", point.getY() = "+ point.getY()

+ "]";

}

transient private Point2D.Double point;

}