为什么数组常量只能用于初始值设定项?

Rit*_*sra 48 java

可能重复:
数组常量只能用于初始值设定项错误

我正在研究数组,我通过这种在一行中声明和初始化数组的简短方法.例如,

int[] a = {1, 2, 3, 4, 5};
Run Code Online (Sandbox Code Playgroud)

但是当我尝试执行以下代码时,我得到了这个编译器错误,说"数组常量只能在初始化程序中使用".

int[] a;
a = {1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)

为什么这样?

NPE*_*NPE 97

这是不允许的,因为JLS这样说.语法仅在声明和数组创建表达式中允许.

后者提供了另一种实现相同结果的方法:

int[] a;
a = new int[]{1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)

至于要求的实际根本原因new T[],我的猜测如下.考虑以下数组初始值设定项:

{1, 2, 3, 4}
Run Code Online (Sandbox Code Playgroud)

它可用于初始化不同类型的数组:

new int[]{1, 2, 3, 4};
new float[]{1, 2, 3, 4};
new double[]{1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)

如果new T[]不需要这个位,我怀疑裸位{1, 2, 3, 4}可能会在语义分析过程中造成困难.在这里,我在考虑以下案例:

void f(float[] x) { ... }
void f(double[] x) { ... }
void g() {
  f({1, 2, 3, 4});
}
Run Code Online (Sandbox Code Playgroud)

如果允许这种语法,则语言规范必须处理选择调用哪个函数的复杂性.

同样,还不清楚应该是什么类型{null}.它可以是Object[],Integer[],Serializable[]等.

最后,空阵列{}将是最棘手的.在这里,我们甚至无法判断它是一个对象数组还是一组标量.

而不是处理所有这些复杂性,似乎语言设计者选择通过要求new T[]语法来避免它们.

  • @DaveNewton:不一定.考虑将"{1,2,3,4}"传递给一个为`float []`和`double []`重载的函数的可能性.应该怎么办? (2认同)

And*_*yle 6

简短的回答是因为语言规范是这样说的.

至于为什么?我怀疑这是打字.在第一种情况下,解析器/编译器知道它在初始化数组变量的上下文中,因此花括号可以推断为数组初始化器.

在后一种情况下,从线上不能立即清楚花括号的含义.据推测,typer在解析的后期阶段运行,因此简单地推断其含义是不可行的.

这个论点似乎很重要,因为如果你特意(并且在技术上冗余地)再次声明类型,你可以使用非常相似的语法:

int[] a;
// then later
a = new int[] { 1, 2, 3, 4 };
Run Code Online (Sandbox Code Playgroud)


cob*_*bie 0

在 java 中,您只能使用第一种方法初始化数组。您无法分配数组。理解其中的原因可能涉及一些有关数组如何实现的理论。声明数组时,编译器必须知道数组有多大,因此通过第一行的声明和初始化,编译器可以推断出数组的大小,但不能推断出第二行的大小。

  • OP 已经知道第二个不起作用并询问*为什么*。答案根本没有解决这个问题。 (2认同)