是否可以在 Java 中做类似的事情?即进行编译时初始化?
不,不可能。 Java 允许编译时常量仅用于static final 变量,具有原始类型或字符串类型,在同一行初始化,而不是 null。这可以是“递归”的,并且允许一些基本的数学运算,只要它保持不变(请参阅JLS §15.28)。
至关重要的是,整数数组不算数。
但是,需要问的问题是:为什么你想要它? Java 不像 C,编译时常量不会给你带来任何东西,除了 [A] 如果你有一个包含常量的类文件 A,你在 B 中引用它,然后编译 B,然后 A 是在运行时不可用,没关系。这是真的,但是,这很少或根本不重要,实际上有点烦人(如果你稍后重新编译 A 而没有重新编译 B,如果它是一个常量,B 将不会接受更改),并且 [B] 它可以为你节省一些每次应用程序执行运行一次的代码。
B 也无关紧要 - JVM 启动比最小 C 应用程序的启动贵几个数量级;这个 JVM 启动完全让这里的任何担忧都相形见绌。
因此,很简单,您认为您想要一个编译时间常数,但您可能不想要。如果你真的这样做了,答案很简单:不可能。
如果它不是一个编译时间常数,而是更多关于以简洁的方式编写它,java 有用于 2D 数组的语法糖,但没有特别花哨的语法来制作结构和初始化它们而不命名它们.
请注意,在惯用的 java 中,[] 在类型之后而不是变量之后。是的,你可以在变量之后写它,但没有人这样做 - 这是 30 年前的遗留物,当时 java 语法被明确设计为吸引 C 编码人员。
因此:
public record S(int[] arr, int x) {}
S[] s = {
new S(new int[] {1, 2, 3}, 111),
new S(new int[] {2, 3, 4}, 222),
new S(new int[] {3, 4, 5}, 333)
};
尽可能短。
只有在为变量声明编写初始化表达式时,才能省略 new S[] 部分。 S[] s 是一个变量声明,因此我们可以在此处跳过它,但我们传入的数组值不是,因此,new int[] 部分不可跳过。你可以看中构造函数并执行以下操作:
public record S(int[] arr, int x) {
public S(int x, int... arr) {
this(arr, x);
}
}
// then you can go with:
S[] s = {
new S(111, 1, 2, 3),
new S(222, 2, 3, 4),
new S(333, 3, 4, 5)
};
打高尔夫球比这更进一步会让你变得相当黑暗,非常不习惯和不明智的 java 语法黑客。