博客
关于我
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 多表联合查询:UNION 和 JOIN 分析
查看>>
MySQL 大数据量快速插入方法和语句优化
查看>>
mysql 如何给SQL添加索引
查看>>
mysql 字段区分大小写
查看>>
mysql 字段合并问题(group_concat)
查看>>
mysql 字段类型类型
查看>>
MySQL 字符串截取函数,字段截取,字符串截取
查看>>
MySQL 存储引擎
查看>>
mysql 存储过程 注入_mysql 视图 事务 存储过程 SQL注入
查看>>
MySQL 存储过程参数:in、out、inout
查看>>
mysql 存储过程每隔一段时间执行一次
查看>>
mysql 存在update不存在insert
查看>>
Mysql 学习总结(86)—— Mysql 的 JSON 数据类型正确使用姿势
查看>>
Mysql 学习总结(87)—— Mysql 执行计划(Explain)再总结
查看>>
Mysql 学习总结(88)—— Mysql 官方为什么不推荐用雪花 id 和 uuid 做 MySQL 主键
查看>>
Mysql 学习总结(89)—— Mysql 库表容量统计
查看>>
mysql 实现主从复制/主从同步
查看>>
mysql 审核_审核MySQL数据库上的登录
查看>>
mysql 导入 sql 文件时 ERROR 1046 (3D000) no database selected 错误的解决
查看>>
mysql 导入导出大文件
查看>>