博客
关于我
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/

你可能感兴趣的文章
MySQL 添加列,修改列,删除列
查看>>
mysql 添加索引
查看>>
MySQL 添加索引,删除索引及其用法
查看>>
mysql 状态检查,备份,修复
查看>>
MySQL 用 limit 为什么会影响性能?
查看>>
MySQL 用 limit 为什么会影响性能?有什么优化方案?
查看>>
MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
查看>>
mysql 用户管理和权限设置
查看>>
MySQL 的 varchar 水真的太深了!
查看>>
mysql 的GROUP_CONCAT函数的使用(group_by 如何显示分组之前的数据)
查看>>
MySQL 的instr函数
查看>>
MySQL 的mysql_secure_installation安全脚本执行过程介绍
查看>>
MySQL 的Rename Table语句
查看>>
MySQL 的全局锁、表锁和行锁
查看>>
mysql 的存储引擎介绍
查看>>
MySQL 的存储引擎有哪些?为什么常用InnoDB?
查看>>
Mysql 知识回顾总结-索引
查看>>
Mysql 笔记
查看>>
MySQL 精选 60 道面试题(含答案)
查看>>
mysql 索引
查看>>