6

我有一个类包含大量生成的常量,例如:

public class Constants extends SomeBaseClass {

  // init() is defined in some base class...
  public static final XXX KEY1 = init(...);
  public static final XXX KEY2 = init(...);
  public static final XXX KEY3 = init(...);

  // ...
  public static final XXX KEY2000 = init(...);
}

当生成的常量数量非常多时,这会导致静态初始化器大于 Java 方法大小的上限(即 > 64kb),从而导致编译器错误。一种解决方案是为可以保证生成少于 64kb 字节码的块创建几个“块初始化方法”,以便它们适合一种方法:

public class Constants extends SomeBaseClass {

  public static XXX KEY1;
  public static XXX KEY2;
  public static XXX KEY3;

  // ...
  public static XXX KEY2000;

  static {
    initialise0001To1000();
    initialise1001To2000();
  }

  private static void initialise0001To1000() {
    KEY1 = init(...);
    KEY2 = init(...);
    KEY3 = init(...);
    // ...
  }

  private static void initialise1001To2000() {
    // ...
    KEY2000 = init(...);
  }
}

这样做的缺点是我不能再将常量声明为final,因为它们现在不再直接在静态初始化程序中初始化。

我的问题是,如何以仍然可以生成static final常量的方式规避编译器/JVM 限制?

4

4 回答 4

7

一种选择是使用继承 - 有一系列类Constants1, Constants2, ...,ConstantsN它们都定义了常量,然后让每个类都从前一个继承。然后最终类Constants可以直接从它们中的最后一个继承。这也可以让您标记所有内容final

出于好奇,您是如何最终得到一个如此大的文件,以至于无法将初始化代码放入 64KB 的限制中?

希望这可以帮助!

于 2012-05-31T21:49:18.647 回答
1

我终于找到了一个涉及嵌套类的解决方案。这是用户Loadmaster在对这个答案的评论中提出的。嵌套类有两个优点:

  • private它们允许通过嵌套类向外界隐藏这些变通方法的实现细节
  • 它们允许保持常数final

但与templatetypedef 的解决方案相比,它们也有一个缺点:

  • 我将再次遇到同样的问题,常量数量要多得多

然而,现在这似乎是最合适的解决方案:

public class Constants {

  public static XXX KEY1    = Constants1.KEY1;
  public static XXX KEY2    = Constants1.KEY2;
  public static XXX KEY3    = Constants1.KEY3;

  // ...
  public static XXX KEY2000 = Constants2.KEY2000;

  // Nested class holding 1000 constants
  private static class Constants1 extends SomeBaseClass {
    KEY1 = init(...);
    KEY2 = init(...);
    KEY3 = init(...);
    // ...
  }

  // Nested class holding the next 1000 constants
  private static class Constants2 extends SomeBaseClass {
    // ...
    KEY2000 = init(...);
  }

  // Keep generating nested classes for more constants...
  private static class Constants3 ... {}
}
于 2012-06-03T11:24:36.490 回答
0

这不行吗? 不。请参阅评论,了解为什么这种答案不能解决问题。

它将允许您将静态变量保持为最终变量,并且更容易自动生成。 然而java将所有的静态init块折叠成一个巨大的静态init块,因此问题没有解决。

public class Constants extends SomeBaseClass {

  // init() is defined in some base class...
  public static final XXX KEY1 ;
  static
  {
       KEY1 = init(...);
  }
  public static final XXX KEY2 ;
  static
  {
       KEY2 = init(...);
  }
  public static final XXX KEY3 ;
  static
  {
       KEY3 = init(...);
  }

  // ...

}
于 2012-05-31T23:53:04.450 回答
-1

您可以拥有任意数量的静态初始化块。

于 2012-06-01T00:28:08.737 回答