- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我阅读了各种关于序列化和 serialVersionUID 使用的博客。他们中的大多数都提到使用它来维护可序列化类的状态。
我的场景是;
我知道旧的 serialVersionUID 和新的 serialVersionUID。
在读取具有旧 serialVersionUID 的对象时,我想操作数据以使其适合新版本,如果我正在读取的对象是旧类型,我只想费心去做。
这看起来应该是非常直接的事情!
有没有办法在读入对象时获取 serialVersionUID?
InvalidClassException 在调用序列化类中的 readObject 方法之前抛出,因此我无法在那里访问它。
我发现的唯一提示是覆盖 ObjectInputStream 以便 readClassDescriptor() 可用,尽管这似乎是解决常见问题的重量级解决方案!
感谢所有帮助!
中号
最佳答案
我将介绍几种在序列化中支持旧版本类/接口(interface)的可能方法:
使用迁移器
在这种情况下,您的 Java 项目中需要以下内容:
@Deprecated
让我从一开始就说,并不总是可以使用旧版本的对象(请参阅 versioning of serializable objects 上的 Oracle 文档)。为了简单起见,让我们假设在升级时,您的类总是实现您定义的接口(interface) IEntity
。
public interface IEntity extends Serializable {
// your method definitions
}
并假设您最初使用该类:
public class Entity implements IEntity {
private static final long serialVersionUID = 123456789L;
// fields and methods
}
如果您需要将类 Entity
升级为具有新 serialVersionUID 的新实现,则首先将其注释为 @Deprecated
但不要重命名并且不要将其移动到另一个包 :
@Deprecated
public class Entity implements IEntity {
private static final long serialVersionUID = 123456789L;
// fields and methods
}
现在使用一个新的 serialVersionUID(重要)和一个额外的构造函数创建您的新实现,如下所示...
public class Entity_new implements IEntity {
private static final long serialVersionUID = 5555558L;
public Entity_new(IEntity){
// Create a new instance of Entity_new copying the given IEntity
}
}
当然,整个过程中最关键的部分是如何实现上面的构造函数。如果您已经将旧类型 Entity
的一些对象序列化为二进制文件(例如使用 ObjectOutputStream
)并且您现在已经迁移到 Entity_new
您可以将它们解析为 Entity
的实例,然后将它们转换为 Entity_new
的实例。这是一个例子:
public class Migrator {
private final IEntity entity;
private Class<? extends IEntity> newestClass = Entity_new.class;
public Migrator(final IEntity entity){
this.entity = entity;
}
public Migrator setNewestClass(Class<? extends IEntity> clazz){
this.newestClass = clazz;
return this;
}
public IEntity migrate() throws Exception {
Constructor<? extends IEntity> constr =
newestClass.getConstructor(IEntity.class);
return constr.newInstance(this.entity);
}
}
当然还有其他替代方案不需要特定的构造函数或使用 java reflection 。还有许多其他设计方法可供选择。另请注意,为简化上述代码,已完全省略异常处理和空对象检查。
设计一个通用的可序列化接口(interface)
如果适用,您可以首先尝试为您的类设计一个将来不太可能更改的接口(interface)。如果你的类需要存储一组极有可能被修改的属性,可以考虑为此使用一个Map<String, Object>
,其中String
指的是属性名/标识符,Object
是对应的值。
自定义 readObject 和 writeObject
还有另一种方法可以为旧版本提供支持,为了完整性我会提到它,但我不会选择这种方法。您可以以适应类/接口(interface)的当前和所有先前版本的方式实现 private void readObject(ObjectInputStream in)
和 private void writeObject(ObjectOutputStream out)
。我不确定这样的事情是否总是可行和可持续的,您最终可能会非常困惑和冗长地实现这些方法。
替代序列化技术
这并没有回答 OP 的问题,但我认为值得提出来。您可以考虑以某种 ASCII 格式(例如 JSON、YAML 或 XML)序列化您的对象。在这种情况下,除非您大力重新设计可序列化接口(interface),否则可扩展性是开箱即用的。如果您正在寻找可扩展的二进制协议(protocol),BSON(二进制 JSON)是一个不错的选择。也许这是在可能无法用 Java 实现的软件之间提供对象可移植性的最佳方式。
关于java - 升级 Java Serializable 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5005330/
实现了Serializable接口(interface)的类的子类是否也实现了Serializable?也就是说子类的实例也可以序列化吗? 最佳答案 I wanted to ask whether t
当对象可序列化或不可序列化时,将数据对象保存到数据库有什么不同。 例如:我有一个名为 Book 的域类 class Book implements Serializable{ private int
我的理解是conflict serializable 隐含serializable。我不确定这如何让他们与众不同。可序列化是否意味着冲突可序列化? 最佳答案 冲突可序列化是可序列化的一个子集,因此仅仅
我正在阅读接口(interface) Serializable 的文档,我在其中找到以下几行: To allow subtypes of non-serializable classes to be
scala @Serializable 的 Action 方式与Java Serializable 不同吗? 我的意思是序列化对象的方式还是两者都使用相同的标准序列化? 最佳答案 Scala 可以编译
我遇到过使用这两种表示法中的任何一种的例子。我找不到关于它的任何信息,说明哪一个是常见的,为什么允许使用 2 个符号,以及两者之间是否存在任何细微差别。 有人有想法吗? 最佳答案 不,没有功能差异。
“可序列化”类中的字段应该是 transient 的或可序列化的,可以修复在另一个类中使用的任何实体/类,但当在甚至无法创建的 dto 类中声明 List/Map 时,就会发生这种情况也一样短暂。请让
我面临任务不可序列化的问题,我检查了其他答案并使我的调用和调用类可序列化。我的代码就像 - public class MultiClassification implements Serializab
我到处都读到 Java Serializable 比 Parcelable 慢得多。 Kotlin Serializable 也是这样吗?或者 Kotlin Serializable 和 Kotlin
描述: 我有一个 ArrayList,它接受任何实现 Serializable 的类。我什至可以将实现 Serializable 的类的实例添加到这个数组列表中,而不会出现任何编译错误。 Java 泛
我正在实现一个可序列化的类(因此它是一个使用 RMI 的值对象)。但我需要测试它。有没有办法轻松做到这一点? 澄清:我正在实现这个类,所以在类定义中粘贴 Serializable 很简单。我需要手动对
我尝试执行以下简单代码。 System.out.println() 不打印单词“Serialized:”。输出为true。 ArrayList arrayList = new ArrayList();
伙计们,我有一个最简单的类,我想成为 Parcelable。我正在按照以下方式进行: public class MyField implements Serializable, Parcelable
我的问题与this 非常相似除了这个问题我在 SonarLint V3 (squid:S1948) 中遇到过。 我的代码是: public class Page implements Serializ
考虑下面的类(class)。如果我对它运行 Findbugs,它会在第 5 行但不在第 7 行给我一个错误(“可序列化类中的非 transient 非可序列化实例字段”)。 1 public clas
当我在 Spark(由 java 编写)应用程序中使用 UDF 函数时,出现此错误。 org.apache.spark.SparkException:任务不可序列化 在 org.apache.spar
我正在使用KTOR框架在我的Android应用程序中发出http请求。我在运行项目时遇到错误。。插件:。依赖关系:。模型类:。接口调用:。我花了几个小时寻找解决方案。我遵循了许多线索,但都没有奏效。我
我发现有人回答了可线性化和可串行化之间的差异,但我没有发现有人说可串行化与顺序一致性相同或不同。 此外,我在不同的文章、书籍和网页中对上述术语的不同定义感到震惊,我把这一切都搞糊涂了。 有人可以解释可
我读过几个相关的问题,但没有一个是更有趣的情况。 这是我的问题,假设我有课 class A implements Serializable { private int a; priva
我注意到在 Spring-boot 中很多人创建模型/实体并实现 Serialiazable 接口(interface)。 public class ModelBase implements Seri
我是一名优秀的程序员,十分优秀!