在Java中,我们可以定义一个数组变量并像这样初始化它:
int[] prime10 = new int[] { 2, 3, 5, 7 };
在JLS中,分配的右侧称为ArrayCreationExpression
。 JLS语法术语中的初始化程序为ArrayInitializer
。
与所有表达式一样,ArrayCreationExpression
可以在方法调用参数列表中使用:
callMe(new int[] { 2, 3, 5, 7 });
但是,我们也可以使用VariableInitializer
的短形式,仅使用ArrayInitializer
:
int[] prime10 = { 2, 3, 5, 7 };
但是我们不能在method call
中使用相同的初始化程序// ILLEGAL IN JAVA
callMe({ 2, 3, 5, 7 });
在分析语法时,为什么编译会失败是可以理解的-JLS摘录:
VariableDeclarator:
VariableDeclaratorId [= VariableInitializer]
VariableInitializer:
Expression
ArrayInitializer
MethodInvocation:
MethodName ( [ArgumentList] )
// plus other variants...
ArgumentList:
Expression {, Expression}
但是为什么要做出这样的决定?为什么不将ArrayInitializer
设为Expression
,或者至少在ArrayInitializer
上添加带有ArgumentList
的变体?显然是句法上的,还是有其他原因(可能是类型推断)阻止了这种扩展?
更新
经过一番技术上的澄清后,“如何知道{1, 2, 3}
的类型”。
在方法调用中,由方法形式参数决定允许的参数类型。因此,如果我有一个方法声明:
void callMe(Number[] numbers) {
//...
}
然后询问电话
callMe({ 1, 2, 3 }); // still ILLEGAL in Java
会平均值
callMe(new Number[] { 1, 2, 3 });
所以这里没问题。我的问题不是出于固执己见的“谁需要此东西”(无论如何谁都需要lambda,钻石和var
;)-而是,从JLS的角度,或者至少从角度来看,是什么阻止(正式)这样的构造? Java架构师将此类功能引入语言的观点?
答案 0 :(得分:2)
{2, 3, 5, 7}
的数组类型是什么?
byte [] ???短[] ??? char [] ??? long [] ???
如果有明确说明,它就在那里。如果使用确定的任何规则来推断它,那么对于开发人员来说,这又是另一条需要学习的规则。
(PS在变量初始值设定项中,可以从变量的类型声明中推断出来。在方法调用中,不能从方法签名中推断出来,因为方法绑定的工作方式完全相反:必须先知道参数类型因为它们是确定涉及哪种方法的决定因素。)
答案 1 :(得分:2)
为什么做出这样的决定是可以理解的。您建议采用哪些规则集来推断{1、2、3}或{1,“ dasqwe”,“ c”}等的类型?造成的问题多于解决的问题。