2

我正在研究一个在不同版本的类(来自序列化二进制表示)之间向后兼容的框架。

我坚持的一件事是如何在运行时用不同版本的字段类替换类中使用的字段。

如果所讨论的类是父对象( Java - 如何加载同一类的不同版本?),我知道如何使用 Classloader 来做到这一点。

但是当我已经有一个对象并且需要更改它的一个字段(或者我不知道如何)时,这不起作用。反射 API 似乎也没有在实例化类后设置类的方法。

我会举一个例子,以便更好地理解。假设我有一个包装类:

class Wrapper{
  int version;
  Object content;
}

现在假设我作为变量内容加载的类在 20 个版本前发生了变化。不过,我仍然拥有当时使用的原始 .java(或 .class-)文件。我打算做的是,使用旧类版本的内容创建一个包装器实例,从光盘加载它,对其进行转换并将其写入最新版本的包装器,其中包含用于内容的当前版本的类。

它还需要非常通用,这就是为什么我在包装器中使用对象而不是实际类的原因。真正的问题是我需要它来进行 protostuff 运行时(反)序列化。这意味着我将 Wrapper.class 传递给 protostuff 并为其生成序列化模式。这目前失败,因为 wrapper.class 文件自动引用新版本(它在项目的包中)。

Schema<Wrapper> schema= RuntimeSchema.getSchema(Wrapper.class);
Wrapper resultWrapper = schema.newMessage();

我不确定这是否会通过类加载器,如果是的话,什么时候。我想它必须,但我不确定什么时候会发生。

解决这个问题的最佳方法是什么?

4

1 回答 1

1

您可以做的一件事是ClassLoader为不同的版本设置单独的对象。由于它ClassLoader是类标识的一部分,因此除了它的包和名称之外,您还可以在内存中拥有该类的多个版本。这种方法的唯一问题是您最终将依赖反射来对这些对象执行任何操作。

然后,您可以创建当前版本的对象并使用反射传输这些字段的值。这将解决在运行时必须修改字段类型的问题。

于 2015-02-24T15:50:02.703 回答