【问题标题】:Compile time initialization of an array of classes with an array of ints inside类数组的编译时初始化,其中包含一个整数数组
【发布时间】:2021-08-22 02:48:44
【问题描述】:
struct S
{
    int arr[3];
    int x;
};


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

以上代码是C++

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

【问题讨论】:

  • String arr [] = {"Hello", "World"};
  • @ScaryWombat - 我的示例在每个类对象中都有一个数组 int
  • 您将使用类而不是struct。看到这个答案stackoverflow.com/a/60959439/2310289
  • @ScaryWombat - 是的,我知道。我的问题是如何在 S 的每个实例中初始化 S::arr 的 3 个元素
  • 你将它们作为参数传递给构造函数。

标签: java arrays initialization


【解决方案1】:

是否可以在 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 语法黑客。

【讨论】:

  • 谢谢 - 但new S(new int[] {1, 2, 3}, 111}), 这似乎缺少{
  • 相反,应该删除最后的}
  • 您能否展示您如何在第一个示例代码中定义 S - 我无法编译它
  • “Java 语法被明确地设计为吸引 C 程序员”......而 C 被明确地设计为吸引 B 程序员,而且...... 真是令人震惊,有多少糟糕的语法通过这条路,以及通过 1960 年代最好的语法设计者的途径:我指的是 Wirth 和 Hoare。
  • @user93353 第一个代码段适用于我,但它确实需要 Java 16 或每当引入记录时(我打瞌睡)。
猜你喜欢
  • 1970-01-01
  • 2012-11-08
  • 2016-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 2020-05-28
相关资源
最近更新 更多