序列化与反序列化

概念的理解:
对象序列化: 将对象写入一个字节流保存起来的过程,稍后你就可以运用序列化过程存储这些对象到一个固定的存储区域如文件, 这种机制叫做对象序列化。
反序列化: 跟序列化正好相反,从一个固定区域如文件读取回内存的过程。
反序列化的时候不会调用对象的任何构造方法,仅仅根据所保存的对象的状态信息在内存中重新构建对象。

Java的序列化和反序列化工具被设计出来,很多情况下,对象的存储和回复工作是自动进行的。 如果你想自己控制这个序列化的过程,比如需要压缩或者加密的时候,你可以使用Exterbalizable接口。

持久化:将一个对象保存到永久存储设备上称为持久化。

一个对象要想能够实现序列化,必须实现Serializable 接口或者Exterbalizable接口(这个接口继承自Serializable 接口), Serializable 接口里面什么都没有,只要看到这个关键字就意味着该对象是可以被序列化的。

一个类若想被序列化,则需要实现 java.io.Serializable 接口,该接口中没有定义任何方法,是一个标识性接口(Marker Interface) ,当一个类实现了该接口,就表示这个类的对象是可以序列化的。

序列化的一些特点:
1、 在序列化时,static 静态变量是无法序列化的;
2 、 如果一个对象的成员也是一个对象,那么这个对象的数据成员也会被保存。如果 A包含了对B的引用,那么在序列化A 的时候也会将 B 一并地序列化。
3、如果一个可以序列化的对象中包含着一个不可序列化的对象作为其成员变量,那么整个序列化过程会失败。 特殊的方法: 当这个成员被标记为transient时,此时序列化过程不会失败,因为程序不会把这个变量加入到序列化的过程之中。A包含了对B的引用,如果A 可以序列化,B 无法序列化,那么当序列化 A 的时候就会发生异常,这时就需要将对 B 的引用设为 transient,该关键字表示变量不会被序列化。

ObjectOutputStream 针对对象的读写
ObjectInputStream

需要注意的一点:在序列化和反序列化的时候,如果有需要特殊处理的类,可以在要序列化的类中重写writeObject 和readObject方法,但是此时序列化和反序列的过程就由你自己来控制了,此时你定义为transient的成员变量也可以被序列化了。 如果你在类中没有重写这两个方法,那么序列化的时候会调用系统自身默认的序列化方法。

private void writeObject(java.io.ObjectOutputStream out)
     throws IOException{
     }
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException{
     }

当我们在一个待序列化/反序列化的类中实现了以上两个 private 方法(方法声明要与上面的保持完全的一致) ,那么就允许我们以更加底层、更加细粒度的方式控制序列化/反序列化的过程。

在写程序的时候,我发现了一个问题:
readObject() readInt()等方法返回的时候如果读取到文件末尾,返回的绝对不是一个null 值

ObjectInputStream无论是读对象,还是记取int等java的基本数据类型,在判结束时,绝对既不是-1,也不是什么null。

若文件中有若干个int的数,你用DataInputStream中的readint()去读,何时判读到结尾?绝对既不是-1,也不是什么null

同样道理:若文件中有若于个Object对象,你用ObjectInputStream中的readObject()去读,何时判读到结尾?绝对既不是-1,也不是什么null

所以使用while循环判断读取一个对象到末尾是不行的,

        while (null != (p = (Person) objIn.readObject())){
            System.out.println(p.id+p.name);
        }

查看的网上的,提供了两种方法:

/* 
 * 若文件中有若干个Object对象,你用ObjectInputStream中的readObject()去读,何时判读到结尾? 
 * 方法之一:(常用的方法)将若干个对象(数量不定)都装入一个容器中(如:ArrayList之类), 
 * 然后将对象都放在一个容器里面,读取就行了。读取时,只要读取一个对象(即容器对象)就行了。 
 *  ArrayList list = ois.readobject();
 * 
 * 
 * 方法之二:(若不想用容器),则由于数量不定,正是用异常EOFException来判断结束。 
 * 代码结构如下:(无论是readInt()读int,还是readObject()读对象)  
 * try{ 
 *  while(true) { 
 *   Object o=ois.radObject();  
 *   处理已读出的对象o;  
 *   } 
 *  } 
 *  catch(EOFException e){  
 *  //已从流中读完。  
 *  }  
 *  finallly { 
 * 流的关闭。 } 
 */  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值