Java学习-序列化

参考资料: html

http://www.2cto.com/kf/201405/305380.html java

http://www.cnblogs.com/xdp-gacl/p/3777987.html 数据库

 

  1. 序列化和反序列化的概念

  把对象转换为字节序列的过程称为对象的序列化 服务器

  把字节序列恢复为对象的过程称为对象的反序列化 网络

  对象的序列化主要有两种用途: 并发

  1 把对象的字节序列永久地保存到硬盘上,一般存放在一个文件或者数据库中; 工具

  2 在网络上传送对象的字节序列。 spa

  在不少应用中,须要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。好比最多见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,因而Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。 htm

  当两个进程在进行远程通讯时,彼此能够发送各类类型的数据。不管是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方须要把这个Java对象转换为字节序列,才能在网络上传送;接收方则须要把字节序列再恢复为Java对象。 对象

  1. 什么状况下须要序列化 

  • 当你想把的内存中的对象保存到一个文件中或者数据库中时候;
  • 当你想用套接字在网络上传送对象的时候;
  • 当你想经过RMI传输对象的时候;
  1. 如何实现序列化

将须要序列化的类实现Serializable或者Externalnalizable接口就能够了,Serializable接口中没有任何方法,能够理解为一个标记,即代表这个类能够序列化。

 

  1. 序列化和反序列化例子

若是咱们想要序列化一个对象,首先要建立某些OutputStream(如FileOutputStream、ByteArrayOutputStream等),而后将这些OutputStream封装在一个ObjectOutputStream中。这时候,只须要调用writeObject()方法就能够将对象序列化,并将其发送给OutputStream(记住:对象的序列化是基于字节的,不能使用Reader和Writer等基于字符的层次结构)

而反序列的过程(即将一个序列还原成为一个对象),须要将一个InputStream(如FileInputstream、ByteArrayInputStream等)封装在ObjectInputStream内,而后调用readObject()便可。

/**

*

*/

package com.serializable;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

 

/**

* @author hugo

*

*/

public class Person implements Serializable {

private static final long serialVersionUID = 1L;

private String name="SheepMu";

private int age=24;

public static void main(String[] args)

{//如下代码实现序列化

try

{

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));

//输出流保存的文件名为 my.out ;ObjectOutputStream能把Object输出成Byte流

Person Person=new Person();

oos.writeObject(Person);

oos.flush(); //缓冲流

oos.close(); //关闭流

} catch (FileNotFoundException e)

{

e.printStackTrace();

} catch (IOException e)

{

e.printStackTrace();

}

fan();//调用下面的 反序列化 代码

}

public static void fan()//反序列的过程

{

ObjectInputStream oin = null;//局部变量必需要初始化

try

{

oin = new ObjectInputStream(new FileInputStream("my.out"));

} catch (FileNotFoundException e1)

{

e1.printStackTrace();

} catch (IOException e1)

{

e1.printStackTrace();

}

Person mts = null;

try {

mts = (Person ) oin.readObject();//由Object对象向下转型为Person对象

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

System.out.println("name="+mts.name);

System.out.println("age="+mts.age);

}

}

 

 

 

五、序列化ID

序列化 ID 在 Eclipse 下提供了两种生成策略,一个是固定的 1L,一个是随机生成一个不重复的 long 类型数据(其实是使用 JDK 工具生成),在这里有一个建议,若是没有特殊需求,就是用默认的 1L 就能够,这样能够确保代码一致时反序列化成功。这也多是形成序列化和反序列化失败的缘由,由于不一样的序列化id之间不能进行序列化和反序列化。

 

6.序列化前和序列化后的对象的关系

是 "=="仍是equal? or 是浅复制仍是深复制? 

答案:深复制,反序列化还原后的对象地址与原来的的地址不一样

序列化先后对象的地址不一样了,可是内容是同样的,并且对象中包含的引用也相同。换句话说,经过序列化操做,咱们能够实现对任何可Serializable对象的"深度复制(deep copy)"——这意味着咱们复制的是整个对象网,而不只仅是基本对象及其引用。对于同一流的对象,他们的地址是相同,说明他们是同一个对象,可是与其余流的对象地址却不相同。也就说,只要将对象序列化到单一流中,就能够恢复出与咱们写出时同样的对象网,并且只要在同一流中,对象都是同一个。

 

7.静态变量可否序列化

序列化会忽略静态变量,即序列化不保存静态变量的状态。静态成员属于类级别的,因此不能序列化。即 序列化的是对象的状态不是类的状态。这里的不能序列化的意思,是序列化信息中不包含这个静态成员域。最上面添加了static后之因此仍是输出24是由于该值是JVM加载该类时分配的值。注:transient后的变量也不能序列化

八、总结:

a)当一个父类实现序列化,子类自动实现序列化,不须要显式实现Serializable接口;

b)当一个对象的实例变量引用其余对象,序列化该对象时也把引用对象进行序列化;

c) static,transient后的变量不能被序列化;

相关文章
相关标签/搜索