Java序列化与反序列化最全详解

什么是序列化和反序列化?

序列化:

  • 序列化就是将 java对象 转化为字节序列的过程。
  • 序列化是指把一个Java对象变成二进制内容,本质上就是一个byte[]数组。 为什么要把Java对象序列化呢?因为序列化后可以把byte[]保存到文件中,或者把byte[]通过网络传输到远程,这样,就相当于把Java对象存储到文件或者通过网络传输出去了。

注意:序列化是为了在传递和保存对象时,为了保证对象的完整性和可传递性。将对象转为有序的字节流,以便在网上传输或者保存在本地文件中。

反序列化:

  • 反序列化就是将 字节序列恢复为java对象的过程。
  • 有序列化,就有反序列化,即把一个二进制内容(也就是byte[]数组)变回Java对象。有了反序列化,保存到文件中的byte[]数组又可以“变回”Java对象,或者从网络上读取byte[]并把它“变回”Java对象。

注意: 反序列化就是根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。

《 Effective Java 》中序列化一节关于java的序列化存在如下说法:

对象序列化(objectserialization)API,它提供了一个框架,用来将对象编码成字节流(serializing),并从字节流编码中重新构建对象(deserializing)。一旦对象被序列化后,它的编码就可以从一台正在运行的jvm传到另一台jvm上,或者被存储在磁盘上,供以后反序列化时用(如tomcat的session的可持久化)。序列化技术为 远程通信 提供了标准的线路级对象表示法,也为JavaBeans组件结构提供了标准的 持久化 数据格式。

网络传输的Http请求和JOSN传输,XML传输。

使用场景

  • 系统之间的DTO对象传输
  • 将对象保存到本地文件中
  • 网络数据传输
  • 等等

网络传输中前后端数据交互的对象,json等与序列化的关系?

  1. 为什么说网络传输的对象要序列化,而字符串不需要用序列化?
  • 网络传输需要将对象转换成字节流传输,序列化可以将一个对象转化成一段字节编码,以便在网络上传输或者做存储处理,使用时再进行反序列;
  • 而字符串不用序列化的原因是字符串String是已经实现了Serializable接口的,所以它已经是序列化了的。
    Java序列化与反序列化最全详解_第1张图片
  1. JSON与对象序列化的关系,json是否需要序列化?
  • json 是一种格式!并不是一个对象,所以不需要序列化。
  • 数据传输中,经常使用JSON格式进行数据传输,也就是用json字符串进行数据传输。json字符串也就是字符串,是已经实现了Serializable接口的。
  • 以 fastjson,中 的JSONObject为例,JSONObject 也是有实现Serializable接口的。所以当在代码中,将对象转化成JSONObject 或者 JSON字符串后,就是都转成已经实现Serializable接口的对象了。
  1. 前后端的数据传输中为什么对象没序列化也能传输?
  • 前后端数据交互是有两种载体。一种是以json字符串或者就是普通字符串进行传输,一种是以实现serializable持久化对象进行传输。
  • 通常在控制器里使用@RequestBody和@ResponseBody等这些注解,框架会自动帮我们将对象转成JOSN,或者将JSON转成对象。这样就算对象没有实现serializable,也是可以正常进行数据传输的。
    // 使用fastjson,将Java对象与json字符串进行互相转换。
    // 将Java对象序列化为Json字符串  
    String objectToJson = JSON.toJSONString(initUser());  
    System.out.println(objectToJson);  
    // 将Json字符串反序列化为Java对象  
    User user = JSON.parseObject(objectToJson, User.class);  
    System.out.println(user);  
 

对象如何进行序列化和反序列化

  1. 对象要实现java.io.Serializable接口。
  2. 增加序列化 ID(private static final long serialVersionUID)。

比如:字符串的代码为例

Serializable接口:

Java类通过实现java.io.Serialization接口来启用序列化功能,未实现此接口的类将无法将其任何状态或者信息进行序列化或者反序列化。可序列化类的所有子类型都是可以序列化的。序列化接口没有方法或者字段,仅用于标识可序列化的语义。

序列化 ID

java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。

序列化例子: 将对象序列化存到文件中,再反序列化回来。

   public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 序列化到磁盘
        FileOutputStream fos =  new FileOutputStream("test.out");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        Test  test = new Test();
        test.setName("alex");
        oos.writeObject(worker);
        oos.flush();
        oos.close();

        // 反序列化磁盘数据并解析磁盘数据
        FileInputStream fis =  new FileInputStream("test.out");
        ObjectInputStream  ois = new ObjectInputStream(fis);
        Test test = (Test) ois.readObject();
        System.out.println(test.getName());
    }

你可能感兴趣的:(java,java)