我有一个类保存了大量生成的常量,如下所示:
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 限制?
一个选择是使用继承 - 拥有一系列类
Constants1
、Constants2
、...、ConstantsN
,它们都定义常量,然后让每个类继承前一个类。 最后一个类Constants
可以直接继承最后一个类。 这还可以让您标记所有内容final
。
出于好奇,你是如何得到一个如此大的文件以至于无法将初始化代码放入 64KB 限制的?
希望这有帮助!
我最终寻求了一个涉及嵌套类的解决方案。这是用户 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 ... {}
}
这行不通? 不。 请参阅评论以了解为什么这种答案无法解决问题。
它将允许您将静态变量保留为最终状态,并且更容易自动生成。 然而,java将所有静态初始化块折叠成一个巨大的静态初始化块,因此问题并没有解决。
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(...);
}
// ...
}
您可以拥有任意数量的静态初始化块。