我有以下问题:
1)有一些抽象类A,其中有几个匿名子类存储在A的静态字段中。两个匿名子类之间存在循环依赖关系。该抽象类的代码类似于以下内容:
class A implements Serializable
{
public static final A _1 = new A() {
public A foo()
{
return _2;
}
};
public static final A _2 = new A() {
public A foo()
{
return _1;
}
};
public static final A _3 = new A() {
public void bar()
{
// do something
}
};
}
2)类A的实例由序列化中使用的其他对象引用。有些对象由开发人员预先序列化,然后作为二进制数据包含在发布中。
在A类的一些重构之后,在发布版本中更改了匿名子类的二进制名称。我想这可能是由于java编译器版本的不同。从我的机器上生成的.class文件中我可以看到存储在_1,_2和_3字段中的A的匿名子类分别具有名称A $ 1,A $ 2和A $ 3,但是从发布版本中获取的.class文件我可以看到存储在_1,_2和_3字段中的A的匿名子类分别具有名称A $ 2,A $ 3和A $ 1。由于这种预先序列化的数据变得无法使用,我需要以某种方式解决这个问题。
java编译器或JVM是否有任何规范可以说明我的匿名类应该具有哪些二进制名称? JLS表示匿名类的名称应该是封闭类的名称,“$” - 符号和非空数字序列,而不对这些序列设置任何约束。
我相信我不应该依赖匿名类的内部名称,我也知道“正确”的方法来解决这个问题,比如在构建服务器上生成预序列化数据。太糟糕了,我们现在没有太多时间,所以我想知道这个命名差异来自哪里,所以我现在可以解决这个问题。
答案 0 :(得分:4)
我敢挑战一些元素吗?希望它对您有用:
现在,如果要求解决您的短期问题,我看到的唯一方法是将您的类恢复到与先前版本兼容的状态。如果您提到的不同顺序是唯一的区别,我相信以与以前相同的顺序定义匿名类值得尝试!还要注意引用应该向后(对于文件中较早的类),而不是向前(对于文件中稍后的类)。
答案 1 :(得分:1)
我可以猜到它失败的唯一原因是新的Java版本重新排序了类名,因为你引用了_2
中的_1
。也就是说,我不认为你可以依赖这些名称,因为Java不保证它将处理类的字段的顺序(因此,它将创建内部类的顺序)。
但我认为你的问题在其他地方。你得到什么错误?
答案 2 :(得分:1)
你的编译器没有发出任何警告吗?
我相信您可以通过覆盖ObjectInputStream.readClassDescriptor
来阅读数据,而无需依赖当前代码中的匿名类名。替换为“兼容”类的描述符。没有保证可行,但如果您的数据很重要,可能值得一试。