博客
关于我
JAVA 序列化、反序列化以及serialVersionUID
阅读量:147 次
发布时间:2019-02-27

本文共 2827 字,大约阅读时间需要 9 分钟。

前言

最近接手的老项目让我看到了同事们编码的身影。在一次无聊的对话中,我不禁好奇:**这个类为啥要实现序列化?** 有些类没有序列化,另一些却选择序列化,这到底为什么呢?更让人困惑的是,为什么我们新建的类也选择了序列化?**序列化究竟有什么用处?** 通过一系列追问,我发现很多同事对序列化这一概念的理解都很模糊,往往只是盲目地模仿他人。于是,我决定写一篇简明扼要的文章,帮助大家理清思绪,消除对序列化的误解。

序列化与反序列化的基础理解

序列化和反序列化听起来像是对着干的操作。简单来说: - **序列化**:将一个对象转换成一系列二进制数据,便于传输或存储。 - **反序列化**:将序列化后的二进制数据恢复成原来的对象。

顺带提一下,serialVersionUID就像是这个类的身份证一样,用于唯一标识每个类的序列化版本。

结合代码理解序列化

为了更直观地理解序列化,我为大家准备了一个简单的Java类。以下是一个实现`Serializable`接口的狗类: ```java import java.io.Serializable;

public class Dog implements Serializable {

private String name;
private Integer age;

@Override  public String toString() {      return "Dog{" +             "name='" + name + '\'' +             ", age=" + age +             '}';  }  public String getName() {      return name;  }  public void setName(String name) {      this.name = name;  }  public Integer getAge() {      return age;  }  public void setAge(Integer age) {      this.age = age;  }

}

可以看到,这个类实现了`Serializable`接口,标记它可以进行序列化操作。  如果不手动设置`serialVersionUID`,系统会自动为这个类生成一个唯一的序列化版本号。  

为什么需要serialVersionUID

假设我们有一个简单的Dog类,包含两个字段:`name`和`age`。当我们第一次序列化这个类时,系统会默认生成一个`serialVersionUID`,并将对象信息与这个唯一标识存储在文件中。 如果我们随后修改Dog类,增加一个新的字段`nickName`,再次进行序列化操作时,系统会检测到字段数量的变化,从而生成一个新的`serialVersionUID`。这种方法虽然可行,但存在一个问题: 当我们尝试反序列化之前的序列化文件时,系统会发现当前类的`serialVersionUID`与文件中的不一致,导致反序列化失败。 为了避免这种问题,我们可以手动设置`serialVersionUID`。例如: ```java private static final long serialVersionUID = 1L;

这样一来,无论我们对Dog类的字段进行何种修改,只要serialVersionUID保持不变,反序列化操作就能顺利完成。

序列化与反序列化的实际操作

为了更直观地理解,我们可以通过代码实现序列化和反序列化操作。

序列化代码示例

import java.io.writeObject;  import java.io.FileOutputStream;  import java.io ObjectOutputStream;  public class SerializeTest {      public static void main(String[] args) throws IOException {          ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("dogInfo.out"));          Dog dog = new Dog();          dog.setName("阿福");          dog.setAge(1);          objectOutputStream.writeObject(dog);          objectOutputStream.flush();          objectOutputStream.close();      }  }

运行上述代码后,会在指定目录生成一个名为dogInfo.out的文件,文件内容为序列化后的Dog对象字节流。

反序列化代码示例

import java.io.ObjectInputStream;  import java.io.FileInputStream;  public class DeserializeTest {      public static void main(String[] args) throws IOException, ClassNotFoundException {          ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("dogInfo.out"));          Dog dog = (Dog) objectInputStream.readObject();          System.out.println("狗的名字:" + dog.getName());      }  }

运行上述代码后,程序会读取并解析序列化文件,重新获得原来的Dog对象。

序列化字段的注意事项

在序列化过程中,有些字段是不能被自动序列化的: 1. **static**修饰的字段: `static`修饰的字段存在于全局区,而序列化操作主要针对堆区中的对象。因此,`static`字段无法被序列化。
  1. transient修饰的字段:
    transient修饰的字段不会被默认序列化。
  2. 如果需要将这些字段包含在序列化过程中,可以手动进行处理。

    总结

    通过以上内容,我们可以清晰地了解序列化和反序列化的基本概念、`serialVersionUID`的作用以及序列化过程中需要注意的事项。希望这篇文章能帮助大家更好地理解和使用序列化功能。

转载地址:http://znwb.baihongyu.com/

你可能感兴趣的文章
MySQL5.7.18主从复制搭建(一主一从)
查看>>
MySQL5.7.19-win64安装启动
查看>>
mysql5.7.19安装图解_mysql5.7.19 winx64解压缩版安装配置教程
查看>>
MySQL5.7.37windows解压版的安装使用
查看>>
mysql5.7免费下载地址
查看>>
mysql5.7命令总结
查看>>
mysql5.7安装
查看>>
mysql5.7性能调优my.ini
查看>>
MySQL5.7新增Performance Schema表
查看>>
Mysql5.7深入学习 1.MySQL 5.7 中的新增功能
查看>>
Webpack 之 basic chunk graph
查看>>
Mysql5.7版本单机版my.cnf配置文件
查看>>
mysql5.7的安装和Navicat的安装
查看>>
mysql5.7示例数据库_Linux MySQL5.7多实例数据库配置
查看>>
Mysql8 数据库安装及主从配置 | Spring Cloud 2
查看>>
mysql8 配置文件配置group 问题 sql语句group不能使用报错解决 mysql8.X版本的my.cnf配置文件 my.cnf文件 能够使用的my.cnf配置文件
查看>>
MySQL8.0.29启动报错Different lower_case_table_names settings for server (‘0‘) and data dictionary (‘1‘)
查看>>
MYSQL8.0以上忘记root密码
查看>>
Mysql8.0以上重置初始密码的方法
查看>>
mysql8.0新特性-自增变量的持久化
查看>>