栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

管理序列化Java对象的多个版本

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

管理序列化Java对象的多个版本

让我们假设可以使用某种巧妙的策略(设置不存在的字段等)(逻辑上)将旧对象转换为新对象…如何布置源代码?

我看到两种处理方式。首先,

serialVersionUID
除非您想
InvalidClassException
抛出该异常,否则切勿更改该异常。第二条规则是
更改字段的 类型 ,而仅添加或删除序列化自动处理的字段。例如,如果序列化的文件具有该类的版本,
booleansharpTeeth;
但该类没有该字段,则在反序列化期间它将被忽略。如果反序列化的类具有该
sharpTeeth
字段,但文件没有,则
false
在这种情况下它将被初始化为其默认值。

对于要尝试同时处理向前和向后兼容性的分布式系统,这尤其重要。您不想升级应用程序A的版本并破坏依赖于A的另一个应用程序B。通过不更改

serialVersionUID
而是仅添加或删除字段就可以做到。实体的较高版本需要支持较旧的版本,而在较新的字段中没有值,但是较旧的实体不会介意新字段是否可用。这也意味着您也不应更改字段的比例。

序列化非常聪明,但是它不能处理字段的类型更改。您不应该只是

paws
从更改
int
long
。相反,我建议添加一个
longpawsLong
或多个这样的代码,然后编写代码来处理存在
int paws
long pawsLong
具有价值的可能性。

public long getPaws() {    if (pawsLong > 0) {        return pawsLong;    } else {        // paws used to be an integer        return paws;    }}

您还可以编写自己的

readObject
方法在反序列化时进行转换:

private void readObject(java.io.ObjectInputStream in) {    super.readObject(in);    // paws used to be an integer    if (pawsLong == 0 && paws != 0) {        pawsLong = paws;    }}

如果这对您不起作用,那么自定义序列化是解决之道。但是,您必须从头开始,

readObject(...)
writeObject(...)
使用内部版本ID
定义自定义和方法。就像是:

// never change thisprivate static final long serialVersionUID = 3375159358757648792L;// only goes upprivate static final int INTERNAL_VERSION_ID = 2;...// NOTE: in version #1, this was an intprivate long paws;private void readObject(java.io.ObjectInputStream in) {    int version = in.readInt();    switch (version) {        case 1 : paws = in.readInt(); ...        case 2 : paws = in.readLong(); ...private void writeObject(java.io.ObjectOutputStream out) {    out.writeInt(INTERNAL_VERSION_ID);    out.writeLong(paws);    ...

但是此方法不能帮助您实现向前兼容性。版本1的读者不会理解版本2的序列化输入。

我应该在一个类加载器中进行反序列化吗?如果失败,请尝试使用另一个使用旧版本(依此类推)的类加载器,还是有更好的方法?

我不会建议任何这些方法。听起来很难维护。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/486364.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号