【发布时间】:2021-11-26 21:09:24
【问题描述】:
我使用The Java® Language Specification Java SE 8 Edition 作为参考。
示例类:
class MyClass {
void method() {
new int[] {0}[0] = 1;
}
}
代码new int[] {0}[0] = 1 应该是Assignment,因为所创建数组的索引0 被赋值为1。
分配由LeftHandSide、AssignmentOperator 和一个表达式组成。在这个例子中,LeftHandSide 应该是new int[] {0}[0]。
LeftHandSide 可以是 ExpressionName、FieldAccess 或 ArrayAccess。在这个例子中,LeftHandSide 应该是一个 ArrayAccess。
问题在于 ArrayAccess。 ArrayAccess 被定义为一个 ExpressionName(本示例不是这种情况)或 PrimaryNoNewArray,然后是括号之间的 Expression。
代码new int[] {0} 是ArrayCreationExpression。 Primary 表达式是 ArrayCreationExpression 或 PrimaryNoNewArray。所以对我来说,ArrayAccess 的第二种情况似乎应该是 Primary 而不是 PrimaryNoNewArray。
我知道 JLS 对所有内容都没有明确的语法,例如带括号的表达式或带括号的 LeftHandSides,但这似乎是一个错误。我检查了最新的规范(Java SE 17),ArrayAccess 的语法没有改变。
【问题讨论】:
-
有点迂腐,但仍然是一个有趣的观察。就我个人而言,我认为这应该是一个编译错误,因为据我所知,代码是无用的,因为创建的数组无法访问。它唯一的潜在影响只是对内存的副作用,如果编译器不烧掉它。
-
@xtratic 您也可以在 while 循环条件中使用它,但这同样没用。
while ((new int[] {0}[0] = 1) > 0) { /* Do stuff */} -
@xtratic 严格来说它不是无用,因为它允许表达式在需要单个表达式的上下文中像语句一样被排序,以获取它们的副作用,例如
new int[] {x += 5, y -= 5, y /= x, x *= y}[3]。这显然是一种不好的用途,但从技术上讲它是一种用途。 -
@Geoff 是的,你可以在任何可以使用表达式结果的地方使用它 (
new int[] {0}[0] = 1),这绝对仍然没用,因为你仍然可以只使用无论如何,赋值操作的右侧表达式。除了潜在的(无法访问的)内存副作用之外,您的示例与while (1 > 0) { /* Do stuff */}基本相同。 -
你写了“我知道 JLS 没有明确的语法,例如括号表达式或括号左手边”,但实际上,括号表达式列在 @987654327 @ as PrimaryNoNewArray,由此得出的结论是,
javac允许,例如(x) = 4;是另一个公然违反规范的行为。
标签: java language-lawyer grammar