小编mik*_*mky的帖子

Java序列化 - 自动处理更改的字段?

更新5月20日:我应该提到有问题的对象确实设置了"serialVersionUID"(旧的和新的都是相同的值),但是在调用readObject()之前序列化失败,但有以下异常:

Exception in thread "main" java.io.InvalidClassException: TestData; incompatible types for field number

我现在还在下面列举一个例子.

我正在使用一个大型应用程序,它从客户端到服务器发送序列化对象(实现Serializable,而不是Exernalizable).不幸的是,我们现在的情况是现有字段完全改变了类型,这打破了序列化.

计划是首先升级服务器端.从那里,我可以控制序列化对象的新版本,以及ObjectInputStream来读取来自客户端的(最初的旧)对象.

我起初想过在新版本中实现readObject(); 然而,在尝试之后,我发现在调用方法之前验证失败(由于不兼容的类型).

如果我是ObjectInputStream的子类,我可以完成我想要的吗?

更好的是,是否有任何第三方库可以进行任何类型的"魔术"?如果有任何工具/库可以将序列化的对象流转换为类似HashMaps的数组,那将非常有趣......无需自己加载对象.我不确定是否可以这样做(将序列化对象转换为HashMap而不加载对象定义本身),但如果可能的话,我可以设想一个可以转换序列化对象(或对象流)的工具)到一个新版本,使用一组属性转换提示/规则等...

谢谢你的任何建议.

5月20日更新 - 下面的示例源 - TestData中的字段'number'从旧版本中的'int'更改为新版本中的'Long'.注意在新版本的TestData中没有调用readObject(),因为在它到达之前会抛出异常:

线程"main"中的异常java.io.InvalidClassException:TestData; 字段编号不兼容的类型

以下是来源.将其保存到文件夹,然后创建子文件夹"旧"和"新".将TestData类的"旧"版本放在"old"文件夹中,将新版本放在"new"中.将"WriteIt"和"ReadIt"类放在main(旧/新的)父文件夹中.'cd'到'old'文件夹,并使用:javac -g -classpath . TestData.java ... 编译, 然后在'new'文件夹中执行相同的操作.'cd'回到父文件夹,并编译WriteIt/ReadIt:

javac -g -classpath .;old WriteIt.java

javac -g -classpath .;new ReadIt.java
Run Code Online (Sandbox Code Playgroud)

然后运行:

java -classpath .;old WriteIt  //Serialize old version of TestData to TestData_old.ser

java -classpath .;new ReadIt  //Attempt to read back the old object using reference to new version
Run Code Online (Sandbox Code Playgroud)

[旧版本] TestData.java

import java.io.*;


public class …
Run Code Online (Sandbox Code Playgroud)

java serialization

9
推荐指数
1
解决办法
5689
查看次数

标签 统计

java ×1

serialization ×1