Java序列化与反序列化

84 阅读3分钟

摘要

本文介绍Java序列化和反序列化,并模拟IDEA中不显式指定序列化ID时的报错场景。

认识序列化和反序列化

序列化:把JVM内存中的对象转换成字节序列(字节流、文件流、网络流、JSON、XML),便于持久化、网络传输和缓存。 

反序列化:把字节序列重新还原成内存中的对象。  

为什么需要序列化和反序列化?

  • 缓存和持久化:将对象存储到文件或数据库中,便于长期保存。 
  • 深拷贝:先序列化再反序列化,可快速得到一个全新对象。 
  • 网络通信‌:在分布式系统中传输对象数据,支持远程调用和实时交互。 
  • 跨平台传输‌:将对象转换为通用格式(如JSON、XML),实现不同平台或语言间的数据交换。  

实体类必须实现Serializable吗?

是的仅用Java原生ObjectOutputStream写磁盘/网络传输 
放入Redis、Kafka、MQ且采用JDK默认序列化 
不是子类继承父类,父子其中一个实现Serializable即可
使用Spring、MyBatis、JPA等仅做ORM映射
放入Redis、Kafka、MQ且采用JSON

IDEA开启SerialVersionUID智能生成实现Serializable,最好显式写明SerialVersionUID打开IDEA设置搜索serialversion,勾选以下选项图片

开启后,实现Serializable时会出现警告,按提示即生成图片

生成成功图片

模拟序列化反序列化失败的场景

1)定义一个对象

package org.coffeebeans;

import java.io.Serializable;

publicclass User implements Serializable {
    //模拟显式指定序列化版本号
 //    private static final long serialVersionUID = 1L;
    // 模拟结构变更
    private int age;

    private String name;
    public String getName() {
        return name;
    }
    public User(String name) {
        this.name = name;
    }
}

2)序列化和反序列化测试

package org.coffeebeans;

import java.io.*;

public class SerializeTest {

    public static void main(String[] args) {
       serialize();
       deserialize();
    }

    static void serialize() {
       User user = new User("测试");
       try (ObjectOutputStream out = new ObjectOutputStream(newFileOutputStream("User.txt"))) {
          out.writeObject(user);
       } catch (Exception e) {
          e.printStackTrace();
       }
       System.out.println("序列化完成");
       /*
          生成二进制文件User.txt:
           sr org.coffeebeans.User6聳帡f狦 L namet Ljava/lang/String;xpt 娴嬭瘯
        */
    }

    static void deserialize() {
       try (ObjectInputStream out = new ObjectInputStream(new FileInputStream("User.txt"))) {
          User user = (User) out.readObject();   // 反序列化
          System.out.println("反序列化成功: " + user.getName());
       } catch (Exception e) {
          e.printStackTrace();
       }
        /*
            没有显式指定序列化ID,序列化后,变更User结构,直接反序列化,结构报错:
            java.io.InvalidClassException: org.coffeebeans.User; local class incompatible:
             stream classdesc serialVersionUID = 3945881762699586119,
             local class serialVersionUID = -7390599950155181816
             at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
             at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
             at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
             at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2000)
             at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)
             at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
             at org.coffeebeans.SerializeTest.deserialize(SerializeTest.java:24)
             at org.coffeebeans.SerializeTest.main(SerializeTest.java:9)
         */
    }

}

总结

以上我们了解了Java序列化和反序列化,并开启了IDEA的序列化ID智能生成器,同时模拟了IDEA中不显式指定序列化ID时的报错场景。

关注公众号:咖啡Beans

在这里,我们专注于软件技术的交流与成长,分享开发心得与笔记,涵盖编程、AI、资讯、面试等多个领域。无论是前沿科技的探索,还是实用技巧的总结,我们都致力于为大家呈现有价值的内容。期待与你共同进步,开启技术之旅。