【问题标题】:What is the Java grammar that allows "new int[] {0}[0] = 1;" to compile?允许“new int[] {0}[0] = 1;”的Java语法是什么编译?
【发布时间】: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}ArrayCreationExpressionPrimary 表达式是 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


【解决方案1】:

看起来严格来说,这不符合指定的语法。但至少,编译器允许它是有意义的:这里使用PrimaryNoNewArray 而不是Primary 的原因是,像new int[1][0] 这样的表达式不能被歧义地解析为二维数组或数组像(new int[1])[0]一样访问。如果数组有一个像new int[]{0}[0] 这样的初始化器,那么语法就没有歧义,因为这不能被解析为创建一个二维数组。

也就是说,由于 JLS 没有指定它是允许的,它可以被视为实现细节或编译器中允许它的错误。

【讨论】:

  • 如果 ArrayCreationExpression 被拆分为两个不同的产生式(一个具有包含 ArrayInitializer 的两种情况,一种具有两种不包含 ArrayInitializer 的情况)可以更新 ArrayAccess 以包括 ExpressionName、PrimaryNoNewArray 和 ArrayCreationExpressionWithInitializer 而无需引入有歧义吗?
  • @Geoff 是的,据我所知,这不会造成任何歧义。
猜你喜欢
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 2011-06-04
  • 2012-03-28
相关资源
最近更新 更多