参考资料: html
http://www.2cto.com/kf/201405/305380.html java
http://www.cnblogs.com/xdp-gacl/p/3777987.html 数据库
把对象转换为字节序列的过程称为对象的序列化。 服务器
把字节序列恢复为对象的过程称为对象的反序列化。 网络
对象的序列化主要有两种用途: 并发
1) 把对象的字节序列永久地保存到硬盘上,一般存放在一个文件或者数据库中; 工具
2) 在网络上传送对象的字节序列。 spa
在不少应用中,须要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。好比最多见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,因而Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。 htm
当两个进程在进行远程通讯时,彼此能够发送各类类型的数据。不管是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方须要把这个Java对象转换为字节序列,才能在网络上传送;接收方则须要把字节序列再恢复为Java对象。 对象
将须要序列化的类实现Serializable或者Externalnalizable接口就能够了,Serializable接口中没有任何方法,能够理解为一个标记,即代表这个类能够序列化。
若是咱们想要序列化一个对象,首先要建立某些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后的变量不能被序列化;