【问题标题】:Anonymous class binary names匿名类二进制名称
【发布时间】:2009-10-05 12:59:50
【问题描述】:

我有以下问题:

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 的实例被序列化中使用的其他对象引用。有一些对象被开发者预序列化,然后作为二进制数据包含在发布中。

在发布版本中更改了匿名子类的类二进制名称的一些重构之后。我认为这可能是由于 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 规定匿名类的名称应该是封闭类的名称、“$”符号和非空数字序列,而不对这些序列设置任何限制。

我相信我不应该依赖匿名类的内部名称,我也知道解决该问题的“正确”方法,例如在构建服务器上生成预序列化数据。太糟糕了,我们现在没有太多时间了,所以我想知道这个命名差异是从哪里来的,所以我现在可以解决这个问题。

【问题讨论】:

    标签: java


    【解决方案1】:

    我敢挑战一些元素吗?希望它对您有用:

    1. 如果你想让你的类有一个众所周知的名字......好吧,匿名与命名类相反! ;-)
    2. 对象作为二进制数据进行预序列化和交付是一个危险的选择,并且您被它所困扰(在重构期间,但我相信这可能在许多其他情况下发生)。序列化数据通常被认为是 Java 中的一种短期解决方案,可以持续几秒钟。许多其他选项可用于长期存储。

    现在,如果要求解决您的短期问题,我看到的唯一方法是将您的类恢复到与以前版本兼容的状态。如果您提到的不同排序是唯一的区别,我相信以与以前相同的顺序定义匿名类值得尝试!还要注意引用应该是向后的(指向文件前面的类),而不是向前的(指向文件后面的类)。

    【讨论】:

    • 我不关注你关于向后引用的评论?您的意思是静态初始化程序顺序有问题吗? / 非瞬态序列化是可以做到的,但是如果你有一些深谋远虑的话会容易得多。
    • @Tom 是的,向后引用避免了静态初始化的一些问题。而且,事物会按照您阅读它们的顺序附加,这在您试图获得精确的顺序时非常重要 :-)
    【解决方案2】:

    我能猜到它失败的唯一原因是新的 Java 版本重新排序了类名,因为您在 _1 中引用了 _2。也就是说,我不认为你可以依赖这些名称,因为 Java 不保证它将按什么顺序处理类的字段(因此,它将创建内部类的顺序)。

    但我认为您的问题出在其他地方。你得到什么错误?

    【讨论】:

    • 在 A$1 类的反序列化过程中出现“本地类不兼容”异常。发生这种情况是因为名称为 A$1 的类定义与序列化期间的不同。
    • 在这种情况下,[这篇文章][informit.com/articles/article.aspx?p=31936] 可能会有所帮助。
    【解决方案3】:

    你的编译器没有给出任何警告吗?

    我相信您可以通过覆盖ObjectInputStream.readClassDescriptor 来读取数据,而无需依赖当前代码中的匿名类名。替换为“兼容”类的描述符。不保证会起作用,但如果您的数据很重要,可能值得一试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-25
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 2014-07-25
      相关资源
      最近更新 更多