类 数组的编译时初始化,其中包含一个整数数组
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 语法黑客。
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 语法黑客。