首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

serialVersionUID-JAVA成长之路

serialVersionUID用作Serializable类中的版本控件。如果您没有显式声明serialVersionUID,JVM将根据您的Serializable类的各个方面自动为您执行此操作,如Java(TM)对象序列化规范中所述。

1. SerialVersionUID示例

上面的语句在开头有点难以理解(至少我做过),让我们开始一个例子来了解Serializable类如何使用SerialVersionUID来实现版本控制。

1.1 Address.java

serialVersionUID为1L的可序列化类。

import java.io.Serializable;

publicclassAddress implements Serializable{

privatestaticfinallongserialVersionUID =1L;

String street;

String country;

publicvoidsetStreet(String street){

this.street =street;

}

publicvoidsetCountry(String country){

this.country =country;

}

publicString getStreet(){

returnthis.street;

}

publicString getCountry(){

returnthis.country;

}

@Override

publicString toString() {

returnnewStringBuffer("Street :")

.append(this.street)

.append("Country :")

.append(this.country).toString();

}

}

1.2 WriteObject.java

将Address对象写入/序列化为文件的简单类 - “c:\\ address.ser”。

import java.io.FileOutputStream;

import java.io.ObjectOutputStream;

publicclassWriteObject{

publicstaticvoidmain (String args[]) {

Address address=newAddress();

address.setStreet("wall street");

address.setCountry("united states");

try{

FileOutputStream fout=newFileOutputStream("c:\\address.ser");

ObjectOutputStream oos=newObjectOutputStream(fout);

oos.writeObject(address);

oos.close();

System.out.println("Done");

}catch(Exception ex){

ex.printStackTrace();

}

}

}

1.3 ReadObject.java

从文件中读取/反序列化Address对象的简单类 - “c:\\ address.ser”。

import java.io.FileInputStream;

import java.io.ObjectInputStream;

publicclassReadObject{

publicstaticvoidmain (String args[]) {

Address address;

try{

FileInputStream fin=newFileInputStream("c:\\address.ser");

ObjectInputStream ois=newObjectInputStream(fin);

address=(Address) ois.readObject();

ois.close();

System.out.println(address);

}catch(Exception ex){

ex.printStackTrace();

}

}

}

2.测试

让我们做一些测试来演示serialVersionUID的使用。

2.1相同的serialVersionUID

相同的serialVersionUID,在反序列化过程中没有问题

javac Address.java javac WriteObject.java javac ReadObject.java java WriteObject java ReadObject Street : wall street Country : united states

复制

2.2不同的serialVersionUID

在Address.java中,将serialVersionUID更改为2L(它是1L),然后再次编译它。

javac Address.java java ReadObject java.io.InvalidClassException: Address; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2 ... at ReadObject.main(ReadObject.java:14)

“ InvalidClassException”会引发,因为您使用serialVersionUID“1L”编写了一个序列化类,但尝试使用更新的序列化类serialVersionUID“2L”将其检索回来。

serialVersionUID必须在序列化和反序列化过程中匹配。

什么时候应该更新你的serialVersionUID?

如果使用对可序列化类的某些不兼容的Java类型更改更新序列化类,则必须更新serialVersionUID。

有关可序列化类的兼容和不兼容Java类型更改的详细信息,请参阅Java对象序列化规范。

3.默认的serialVersionUID有什么问题?

如果没有声明serialVersionUID,JVM将使用自己的算法生成默认的SerialVersionUID,您可以在此处检查算法。

默认的serialVersionUID计算对类详细信息非常敏感,可能因不同的JVM实现而异,并且在反序列化过程中会导致意外的InvalidClassExceptions。

3.1客户端/服务器环境

- 客户端在Windows中使用SUN的JVM。

- 服务器在Linux中使用JRockit。

客户端通过套接字向服务器发送带有默认生成的serialVersionUID(例如123L)的可序列化类,服务器可以在反序列化过程中生成不同的serialVersionUID(例如124L),并引发意外的InvalidClassExceptions。

3.2文件/数据库环境

- App#1在Windows中使用SUN的JVM。

- App#2在Linux中使用JRockit。

序列化允许保存到文件或数据库中。App#1默认生成serialVersionUID(例如123L)将可序列化类存储到数据库中,而App#2可能在反序列化过程中生成不同的serialVersionUID(例如124L),并引发意外的InvalidClassExceptions。

您可以在此处查看JVM实现的列表。

4.如何生成serialVersionUID

您可以使用JDK“ serialver”或Eclipse IDE自动生成serialVersionUID,详见详细信息。

结论

SUN强烈建议开发人员声明serialVersionUID以避免上面列出的不同JVM问题,但我建议您应该了解什么是序列化,serialVersionUID如何实现版本控制以及您的类需要使用序列化的原因。了解serialVersionUID概念优于任何推荐的盲目。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200612A04ST300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券