serialVersionUID的作用

什么是serialVersionUID

序列化是将对象的状态信息转换为可存储或传输的形式的过程。

虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致,这个所谓的序列化ID,就是我们在代码中定义的serialVersionUID。

serialVersionUID是用来验证版本一致性的。

所以在做兼容性升级的时候,不要改变类中serialVersionUID的值

serialVersionUID 既然是验证版本一致性的,在做版本升级的时候(非兼容性升级),记得要修改这个字段的值哦,这样可以避免序列化混乱。

writeFile() 会在E盘生成SerializableDemo.txt文件。

正常情况下,执行readFile()会将name读取出来。

然而,如果将User类中serialVersionUID改变后,再读取readFile()会抛出一个java.io.InvalidClassException,并且指出serialVersionUID不一致。

java.io.InvalidClassException: com.nadou.User; local class incompatible: stream classdesc serialVersionUID = 2736920230361312748, local class serialVersionUID = 2736110230361312748

这是因为,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

这也是《阿里巴巴Java开发手册》中规定,在兼容性升级中,在修改类的时候,不要修改serialVersionUID的原因。除非是完全不兼容的两个版本。所以,serialVersionUID其实是验证版本一致性的。

如果一个类实现了Serializable接口,一定要记得定义serialVersionUID,否则会发生异常。

之所以会发生异常,是因为反序列化过程中做了校验,并且如果没有明确定义的话,会根据类名及属性等自动生成一个

可以实验下,将User类中的private static final long serialVersionUID = 2736920230361312748L; 去掉。

执行writeFile()将文件生成,然后将User类中的age属性去掉,执行readFile()读取,抛出java.io.InvalidClassException,并且指出两个serialVersionUID不同,分别是-7098663385922132191和-4368075718275022011,从这里可以看出,系统自己添加了一个serialVersionUID。

java.io.InvalidClassException: com.nadou.User; local class incompatible: stream classdesc serialVersionUID = 7098663385922132191, local class serialVersionUID = -4368075718275022011

如何idea提示生成serialVersionUID选项

在这里插入图片描述

示例代码:

pom.xml

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>

测试demo

package com.nadou;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.junit.Test;

public class SerializableDemo{
  @Test
  public void writeFile(){
     User user = new User();
     user.setName("lala");
     ObjectOutputStream oos = null;
     try {
       oos=new ObjectOutputStream(new FileOutputStream("E:\\SerializableDemo.txt"));
       oos.writeObject(user);
     } catch (IOException e) {
       e.printStackTrace();
     }finally {
       IOUtils.closeQuietly(oos);
     }
   }
  @Test
  public void readFile(){
     File file = new File("E:\\SerializableDemo.txt");
     ObjectInputStream ois = null;
     try {
       ois = new ObjectInputStream(new FileInputStream(file));
       User user = (User)ois.readObject();
       System.out.println("name:"+user.getName());
     } catch (IOException e) {
       e.printStackTrace();
     } catch (ClassNotFoundException e) {
       e.printStackTrace();
     }finally {
       IOUtils.closeQuietly(ois);
     }
   }

}


class User implements Serializable {

  private static final long serialVersionUID = 2736920230361312748L;

  private String name;
  private int age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值