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

你可能感兴趣的文章
netcat的端口转发功能的实现
查看>>
NetCore 上传,断点续传,可支持流上传
查看>>
Netcraft报告: let's encrypt和Comodo发布成千上万的网络钓鱼证书
查看>>
Netem功能
查看>>
netfilter应用场景
查看>>
Netflix:当你按下“播放”的时候发生了什么?
查看>>
Netflix推荐系统:从评分预测到消费者法则
查看>>
netframework 4.0内置处理JSON对象
查看>>
Netgear WN604 downloadFile.php 信息泄露漏洞复现(CVE-2024-6646)
查看>>
Netgear wndr3700v2 路由器刷OpenWrt打造全能服务器(十一)备份
查看>>
netlink2.6.32内核实现源码
查看>>
netmiko 自动判断设备类型python_Python netmiko模块的使用
查看>>
NetMizer 日志管理系统 多处前台RCE漏洞复现
查看>>
NetMizer-日志管理系统 dologin.php SQL注入漏洞复现(XVE-2024-37672)
查看>>
Netpas:不一样的SD-WAN+ 保障网络通讯品质
查看>>
netron工具简单使用
查看>>
NetScaler MPX Gateway Configuration
查看>>
NetScaler的常用配置
查看>>
netsh advfirewall
查看>>
NETSH WINSOCK RESET这条命令的含义和作用?
查看>>