Java 序列化和反序列化 笔记

Java 序列化和反序列化 笔记

概念及作用:
序列化:将Java对象转化为二进制字节流。
反序列化:将二进制字节流转化为Java对象。
作用:序列化就是一类对象的集合,很多的对象数据,这些数据中,有些信息我们想让它长时间的保存起来,于是就进行序列化。序列化就是把内存里面的这些对象给变成一连串的字节描述,保存在文件之中。反序列化就是把保存在文件里面的东西解析还原成对象。

序列化的过程:

方法有两种:继承Serializable接口(隐式序列化)和继承Externalizable接口(显示序列化)。
只有实现了Serializable和Externalizable接口的类的对象才能进行序列化操作。Externalizable接口继承自Serializable口,实现Externalizable接口的类需要自行控制序列化的行为。实现Serializable接口的类采用默认的序列化方式。

Serializable和Externalizable接口的区别:

  1. 如果一个类实现了Serializable,但他的父类并不是可序列化的,那么该父类必须要有个无参构造函数。
  2. 如果一个类实现了Externalizable,此类必须有公有无参构造函数以便在反序列化时调用。
  3. Serializable接口没有定义方法,也没有定义任何常量。如果有类实现了Serializable接口,则等于告诉JVM此类是可序列化的。对于实现了Serializable接口的类,如果需要类的某个成员变量在序列化时被排除,不参与序列化,可在定义成员变量时,使用transient关键词。
  4. Externalizable接口提供的writeExternal和readExternal两个方法,给予开发者序列化实现的可控。在实现Externalizable接口时,writeExternal,readExternal两方法的传入参数ObjectOutputStream和ObjectInputStream,方法内只能调用他们的writeObject和readObject方法,其他方法无法完成序列化。

两个流对象的作用ObjectInputStream和ObjectOutputStream:

public static void writeObjec(File f) throws IOException{
FileOutputStream outputStream = new FileOutputStream(f); 
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(new Student());
objectOutputStream.close();
} 
public static void readObject(File f) throws IOException, ClassNotFoundException{
FileInputStream inputStream = new FileInputStream(f);
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
Student s2 = (Student) objectInputStream.readObject();
objectInputStream.close();
}

ObjectOutputStream按照默认方式进行序列化时,具有以下特点:
ObjectOutputStream只能对实现了Serializable接口的类的对象进行默认的序列化操作,这种操作仅仅为对象的非transient和非static的实例属性进行序列化。静态属性属于类,不属于对象。静态属性在类加载的时候初始化,将含有静态属性的对象的序列化和反序列化分开在不同的进程中,以得到正确结果。

ObjectInputStream按照默认方式进行反序列化时,具有以下特点:

  1. 如果内存中对象所属的类还没有加载,那么会加载并初始化这个类。如果在classpath中找不到相应的类文件,抛出ClassNotFoundException。
  2. 在反序列化时不会调用类的任何构造方法。

序列化注意的问题:

  1. 序列化和反序列化的顺序要一致
  2. 保存对象的文件名一般不要用.txt文件,换成.obj或.ser文件最好

Transient成员属性:
transient属性不能被序列化,可以修饰以下类型的属性。

  1. 实例属性不代表对象的固有的内部数据,仅仅代表具有一定逻辑含义的临时数据。
    private String firstName;
    private String lastName;
    private transient String fullName;
  2. 实例属性表示一些比较敏感的信息(密码等), 出于安全方面的原因不希望被序列化。
  3. 实例属性需要按照用户自定义的方式序列化,如经过加密后再序列化。

具有关联关系的对象之间的序列化:系统还会序列化此类所关联的其他可序列化的对象。

自定义Serializable接口:
自定义序列化方式,在可序列化类中定义下面两个方法:

private void writeObject(ObjectOutputStream out) throws IOException
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundExce ption

自定义Externalizable接口:
Externalizable接口继承自Serializable接口。如果一个类实现了Externalizable接口,那么将完全由这个类控制自身的序列化行为。

public void writeExternal(ObjectOutput out)throws IOException 
public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException

对实现了Externalizable接口的类的对象进行反序列化操作时,会调用该类无参的构造方法。

默认序列化与自定义序列化的比较:

默认序列化方式的不足:

  1. 对象当中的不易对外公开的敏感数据进行序列化,安全性低。
  2. 不会检查对象的成员属性是否合乎正确的约束条件。
  3. 默认的序列化方式需要对对象图进行递归遍历,如果对象图很复杂,会消耗很多空间和时间,甚至引起Java虚拟机堆栈溢出。

自定义序列化方式两种:

  1. 实现Serializable接口,并且提供private的writeObject()和readObject()。
  2. 实现Externalizable接口,实现writeExternal()和readExternal()方法,必须提供public无参的构造方法。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值