类 数组的编译时初始化,其中包含一个整数数组

Compile time initialization of an array of classes with an array of ints inside

struct S
{
    int arr[3];
    int x;
};


S s[3] = {{{1, 2, 3}, 111},
          {{2, 3, 4}, 222},
          {{3, 4, 5}, 333}};

以上代码为C++

是否可以在 Java 中做类似的事情?即进行编译时初始化?

Is it possible to do something similar in Java? i.e. do a compile time initialization?

不,不可能。 Java 允许编译时常量仅用于 static final 变量,原始类型或 String 类型,在同一行初始化,而不是 null。这可以是 'recursive',并且允许一些基本的数学运算,只要它都保持不变(参见 JLS §15.28)。

那么至关重要的是,整数数组不算数。

但是,需要问的问题是:为什么你想要它? Java 不像 C,编译时常量不会给你带来任何好处,除了 [A] 如果你有 class 包含常量的文件 A,并且你在 B 中引用它,并且然后编译B,然后A在运行时不可用,就无所谓了。这是真的,但是,这很少甚至从不重要,而且实际上有点烦人(如果您稍后在不重新编译 B 的情况下重新编译 A,如果它是常量,B 将不会接受更改),并且 [B] 它可以为您节省一些每次应用程序执行运行一次的代码。

B 也无关紧要 - JVM 启动比最小 C 应用程序的启动贵几个数量级;这个 JVM 启动完全让这里的任何问题相形见绌。

因此,平凡地,您认为您需要一个编译时间常量,但您可能不需要。如果你真的这样做了,答案很简单:不可能

如果与其说它是一个编译时常量,不如说它更简洁,那么java有二维数组的语法糖,但没有特别花哨的语法来制作结构并在不命名的情况下初始化它们。

请注意,在惯用的 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 语法黑客。