Java的序列化流程如下:

Java的反序列化流程如下:

注意:并不是所有类都需要进行序列化,主要原因有两个

1)安全问题。Java中有的类属于敏感类,此类的对象数据不便对外公开,而序列化的对象数据很容易进行破解,无法保证其数据的安全性,因此一般这种类型的对象不会进行序列化。

2)资源问题。可以使用序列化字节流创建对象,而且这种创建时不受限制的,有时过多地创建对象会造成很大的资源问题,因此此类对象也不适宜进行序列化。

Serializable

Serializable是Java提供的一个序列化接口,它是一个空接口,专门为对象提供标准的序列化跟反序列化操作。

序列化过程:

 Person p = new Person("name","id");
File file = new File("cache.txt");
FileOutputStream output = new FileOutputStream(file);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(output);
objectOutputStream.writeObject(p);
output.close();
objectOutputStream.close();

反序列化过程:

      File file = new File("cache.txt");
FileInputStream input= new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(input);
Person p = (Person)objectInputStream.readObject();
System.out.println(p.getName()+"---"+p.getId());
input.close();
objectInputStream.close();
  • 需要序列化的类成员

    对象序列化时并不是所有成员都要转换成二进制的字节序列,因为为了节省存储或传输空间以及提高序列化效率,有些不必要的成员是无需序列化的。其中包括:

    •   静态变量。因为静态变量属于类的属性,并不属于某个具体实例,因此在序列化的时候无须进行序列化,反序列化时,可以直接获取类的静态成员引用。
    •   方法。方法只是一系列的操作集合,方法不会依赖对象,不会因为对象的不同,而操作不同,反序列化时,也可以从类中直接获取方法信息。
  • 继承关系的序列化

    • 父类实现Serializable时,子类被序列化,父类也会被序列化。
    • 父类没有实现Serializable时,子类被序列化,父类不会被序列化
  • 引用关系的序列化

    如果对一个实现了Serializable的类进行序列化操作,则同时对它的引用类进行序列化操作。如果引用类没有实现Serializable接口,JVM会抛出java.io.NotSerializableExeception.

 class Person implements Serializable{
private String name;
private Tool tool = new Tool();
} class Tool implements Serializable{ }

  此时对Person类进行序列化操作,则会同时对Tool类进行序列化操作。若Tool类没有实现Serializable接口,则会抛出异常。

  • 保护敏感数据:

    •   一个类加上序列化标识后,该类对象的所有属性信息将被序列化,然后进行本地存储或网络传输。然后有时对象中的某些字段属于敏感信息,不应暴露出来。如果对其也进行序列化,容易被破解,从而   造成安全隐患,例如常见的密码字段。
    •   Java提供一个关键字transient,即瞬时关键字。该关键字关闭字段的序列化,这样受保护的信息就不会因为序列化而对外暴露。
  • 序列化标识ID

    •   试想一下这样的情景:两端进行网络传输序列化对象,由于某种原因,导致两端使用的类的版本不同,假设接收方的类被删除了几个字段。当发送发将对象的序列化字节流发送到接收方时,由于接收方 的类少了几个字段,而无法解析。
    •   Java要求实现序列化接口的类都必须声明一个serialVersionUID静态属性,如果没有该属性JVM也会自动声明该属性,并为该属性赋值(当类发生改变时会赋予不同的值)。该属性的值是唯一的,用于 标识不同的序列化类。只有类的序列化标识完全相同,Java才会进行反序列化工作,这就是序列化标识的作用。
    •   对于前面提到的情景,假设没有手动声明serialVersionUID,则JVM对发送方跟接收方使用的类中的serialVersionUID赋予不同的值,则反序列化失败。当手动给serialVersionUID赋值时,即使类的字 段发生改变,也能够反序列化成功。
  • 自定义序列化策略

    •   定制序列化策略

      Java提供了一套有效的机制,允许在序列化和反序列化时,使用定制的方法进行相应的处理。当传输双方协定好序列化策略后,只需要在需要传输的序列化类中添加一组方法来实现这组策略,在序列化时会自动调用这些规定好的方法进行序列化和反序列化。方法如下:

     1)private void writeObject(ObjectOutputSteam out) throws IOException  

  在方法的内部有重要的代码:out.defaultWriteObject()    //将对象数据以默认方式写入到输出流中

     2)private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException

  同样的,此方法内部也有相似代码:in.defaultReadObject();  //以默认方式从输入流中恢复对象

这两个方法的作用分别是将特定的对象写入到输出流中以及从输入流中恢复特定的对象,通过这两个方法,用户即可实现自定义的序列化。当在实现Serializable接口的类中写了上面两个方法之后,序列化或反序列化该类时则会通过反射来调用这两个方法,从而实现自定义序列化。

    •   限制序列化对象的数量

      我们看下面的单例模式:

 public class Singleton implements Serializable {

     private volatile static Singleton mInstance;
private Singleton() {
} public static Singleton getInstance() {
if (mInstance == null) {
synchronized (Singleton.class) {
if (mInstance == null) {
mInstance = new Singleton();
}
}
}
return mInstance;
}
}

  此时通过反序列化获取实例,则单例模式会失效。那该如何解决这个问题呢?

  Java有一种机制,可以让我们在序列化和反序列化时,可以根据自己的需要,写入或读取指定的实例。使用这种机制,需要在实现Serializable接口的类中添加两个方法:

  •     private Object readResolve()   //如果用户在序列化类中添加了该方法,则在进行反序列化时,使用该方法返回的对象,作为反序列化对象。
  •     private Object writeReplace()   //如果用户在序列化类中添加了该方法,则在进行序列化时,序列化该类返回的对象。

      再看使用了该机制的单例模式:

  1 public class Singleton implements Serializable {
2
3 private volatile static Singleton mInstance;
4 private Singleton() {
5 }
6
7 public static Singleton getInstance() {
8 if (mInstance == null) {
9 synchronized (Singleton.class) {
10 if (mInstance == null) {
11 mInstance = new Singleton();
12 }
13 }
14 }
15 return mInstance;
16 }
17
18 private Object readResolve() {
19 return getInstance();
20 }
21
22 private Object writeReplace() {
23 return getInstance();
24 }
25 }

  此时的通过反序列化得到的对象也是同一个,即单例模式依然有效!

Java序列化之Serializable的更多相关文章

  1. Java序列化接口Serializable接口的作用总结

    一.Java序列化接口Serializable的作用: 一个对象有对应的一些属性,把这个对象保存在硬盘上的过程叫做”持久化”. 对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字 ...

  2. Java序列化,serializable

    Java 串行化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象.这种机制允许你将对象通过网络进行传播,并可以随时把对象持久 ...

  3. Java 序列化接口Serializable详解

    一个对象序列化的接口,一个类只有实现了Serializable搜索接口,它的对象才是可序列化的.因此如果要序列化某些类的对象,这些类就必须实现Serializable接口.而实际上,Serializa ...

  4. Java序列化接口的作用总结

    一个对象有对应的一些属性,把这个对象保存在硬盘上的过程叫做”持久化”. 把堆内存中的对象的生命周期延长,存入硬盘,做持久化操作.当下次再需要这个对象的时候,我们不用new了,直接从硬盘中读取就可以了. ...

  5. Java 序列化Serializable详解

    Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...

  6. Java序列化与反序列化(Serializable)

    Java序列化与反序列化(Serializable) 特别注意: 1.要序列化的类必须实现Serializable借口 2.在反序列化(读取对象)的时候必须额外捕获EOFException 3.序列化 ...

  7. Java 序列化Serializable详解(附详细例子)

    Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization ...

  8. Java序列化Serializable和Externalizable

    纸上得来终觉浅,绝知此事要躬行  --陆游       问渠那得清如许,为有源头活水来  --朱熹 什么是Java序列化?为什么出现Java序列化?怎样实现Java序列化? 一.什么是Java序列化 ...

  9. Java序列化Serializable

    1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描述的过程:deserialization(反序列化)是一种将这些字节重建成一个对象的过程. 2.什么情况下需 ...

随机推荐

  1. c++构造函数谁先执行的问题

    看到网上一哥们的帖子 http://blog.csdn.net/maray/article/details/7761709 东西不多就转发了 1 #include <iostream> u ...

  2. 学习Swift -- 构造器(上)

    构造器(上) 构造过程是为了使用某个类.结构体或枚举类型的实例而进行的准备过程.这个过程包含了为实例中的每个存储型属性设置初始值和为其执行必要的准备和初始化任务. 构造过程是通过定义构造器(Initi ...

  3. 【Ireport】利用Ireport5.2的table组件迅速制作表格导出pdf

    转载请注明网址.Ireport table dataset Ireport在半年前还是4.7,今天无意发现,居然出到了5.2就搞一把. 首先,去下载Ireport,并进行安装.这个我就不演示了.下载完 ...

  4. wpf 依赖性属性

    1 依赖性属性的作用 在WPF体系中,只有定义属性为依赖项属性,这个属性才支持样式设置,数据绑定,继承,动画和默认值.也就是 这个属性才能具有WPF中的一些特点. 它支持自动通知UI控件. WPF的属 ...

  5. BZOJ1232: [Usaco2008Nov]安慰奶牛cheer

    1232: [Usaco2008Nov]安慰奶牛cheer Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 578  Solved: 403[Submi ...

  6. hadoop2.0安装和配置

    hadoop2与hadoop1的配置有些许不同,最主要的是hadoop1里的master变成了yarn 这篇文直接从hadoop的配置开始,因为系统环境和jdk和hadoop1都是一样的. hadoo ...

  7. 支付返回post请求数据

    点击返回商家返回的post数据: {"requestBody":"singnType=&version=&businessId=00WGFKB20012& ...

  8. C# 中的协变和逆变

    作为一个从接触 Unity 3D 才开始学习 C# 的人,我一直只了解一些最基本.最简单的语言特性.最近看了<C# in Depth>这本书,发现这里面东西还真不少,即使除去和 Windo ...

  9. Counting - SGU 117(快速幂)

    题目大意:求下面N个数里面有多少个数的M次方能整除K 代码如下: ======================================================== #include&l ...

  10. hpuoj 问题 C: 善良的国王【最小生成树kurskal】

    问题 C: 善良的国王 时间限制: 1 Sec  内存限制: 128 MB提交: 112  解决: 48[提交][状态][讨论版] 题目描述 很久很久以前,有一个贫困的国家,这个国家有一个善良爱民的国 ...