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. double类型字符串转换成一个纯数字字符串和一个小数点位数的c++代码

    今天工作中遇到一个要不一个double型的字符串转换成一个纯字数字符串和一个标志这个数字字符串的小数点有几位的int类型 例如:“23.123”--->“23123” + 3   比较简单.就是 ...

  2. 完全靠代码生成的ios版hello,world

    xcode5 运行在iphone retain 3.5" 模式下(即对应iphone4, iphone4s)需要开启ARC // // main.m // Hello // // Creat ...

  3. C++中Reference与指针(Pointer)的使用对比

    整理日: 2015年3月18日 引用(reference)和指针(pointer)是学C++过程中最令人头疼的问题,常常不知道什么时候用哪个合适,又常常弄混.找到Dan Saks的这篇文章,讲的很清楚 ...

  4. Nginx配置免费SSL证书StartSSL,解决Firefox不信任问题

    先在StartSSL上申请免费一年的SSL证书,具体过程网上很多教程.然后把申请到的key和crt文件上传到服务器,比如/usr/local/nginx/certs/. Nginx配置SSL证书 直接 ...

  5. [HDOJ - 5208] Where is Bob 【DFS+按位贪心】

    题目链接:HDOJ - 5208 题目分析 使用按位贪心的思想,即从高位向低位枚举,尽量使这一位的答案为 1 . 我们使用 DFS ,每次就是对于  [l1, r1] [l2, r2] x  进行处理 ...

  6. 【HDU3440】House Man (差分约束)

    题目: Description In Fuzhou, there is a crazy super man. He can’t fly, but he could jump from housetop ...

  7. CyclicBarrier的介绍和使用

    转自:http://www.itzhai.com/the-introduction-and-use-of-cyclicbarrier.html 类说明: 一个同步辅助类,它允许一组线程互相等待,直到到 ...

  8. Delphi在win7/vista下写注册表等需要管理员权限的解决方案

    看到论坛好多人问win7下写注册表的问题,我结合自己的理解写了一点东西,首先声明一下,本人初学Delphi,水平有限,大家见笑了,有什么不对之处请老鸟多指点. [背景]win7/Vista提供的UAC ...

  9. lc面试准备:Regular Expression Matching

    1 题目 Implement regular expression matching with support for '.' and '*'. '.' Matches any single char ...

  10. Android sqlite数据库存取图片信息

    Android sqlite数据库存取图片信息 存储图片:bitmap private byte[] getIconData(Bitmap bitmap){ int size = bitmap.get ...