Java7规范中的语法是否真的相同?

JLS v7 第18章中的语法似乎与文档中其他地方的结构不同,但对我来说似乎存在差异。 特别是在第15章中,规则是:

RelationalExpression: ShiftExpression RelationalExpression  ShiftExpression RelationalExpression = ShiftExpression RelationalExpression instanceof ReferenceType 

这使得foo instanceof Bar成为一个RelationalExpression(因此是一个EqualityExpresson),它又可以在EqualityExpression规则中用作LHS,这使得foo instanceof Bar == false为EqualityExpression。

但是在第18章中查看语法时,他们对它进行了简化:

 Expression2: Expression3 [Expression2Rest] Expression2Rest: { InfixOp Expression3 } instanceof Type 

这看起来很奇怪,这意味着我们可以将Expression3与二元运算符链接在一起,或者我们可以检查一个Expression3的类型。 具体来说,现在foo instanceof Bar是一个Expression2 ,但我没有看到使用Expression2作为相等比较的LHS是有效的。

我是否错过了第18章语法中的一些内容,使得foo instanceof Bar == false是一个有效的表达式? 请注意,根据第15章中的规则并根据我的编译器,它是一个有效的表达式。

这个问题应该得到一个很好的答案,所以让我们仔细看看。

仅基于第18章中的语法:

任何带有InfixOp的东西(例如== )都适合Expression2Rest或者什么都不适合。 Expression2Rest只属于Expression2 。 因此,如果foo instanceof Bar == false是合法的Java,那意味着foo instanceof Bar必须是Expression3

表达式2:
Expression3 [Expression2Rest]

Expression2Rest:
{InfixOp Expression3}
instanceof 类型

但是foo instanceof Bar不是Expression3 。 没有PrefixOp且没有强制转换 ,因此要成为Expression3,它必须是主要的 。 但它只是不合适。

表达式3:
PrefixOp Expression3
(表达式 | 类型) 表达式3
主{选择器} {PostfixOp}

主:
文字
ParExpression
[论点]
超级 SuperSuffix
造物主
NonWildcardTypeArguments(ExplicitGenericInvocationSuffix | this Arguments)
标识符{标识符} [IdentifierSuffix]
BasicType { [] } * .class
void.class

结论:仅基于第18章中提供的语法, foo instanceof Bar == false不是合法的Java表达式。 !?!?!

当然那是胡说八道。 foo instanceof Bar产生一个布尔结果,该结果当然可以与false进行比较。 表达式编译并运行。

更好的结论:第18章不具有权威性,但本书的其余部分是。

第2.3节指出

第4章,第6-10,14和第15章给出了Java编程语言的语法语法。第18章还给出了Java编程语言的语法语法,比说明更适合于实现。

根据第15章中介绍的语法规则, foo instanceof Bar == false 一个合法的Java表达式。 但请查看15.20.1节之前的最后一句:“关系表达式的类型总是布尔值 。” 这与15.20中的RelationalExpression规则本身直接冲突。 (特别是,它意味着instanceof的LHS必须评估为布尔值 。)它不可能是真的。

最好的结论:这本书有问题。 如果你想知道某些东西是否是合法的Java,你必须编译并运行它,最好是在Oracle的参考实现上。 即便如此,也可能存在错误。 毕竟,它只是软件。

我认为,如果他们稍微改变了Expression2规则,那么第18章可能是对的。 像这样:

* Expression2:
Expression3 [ instanceof Type]
Expression2 {InfixOp Expression3}

但谁知道,这可能会导致其他问题。 在任何情况下,它都在Java 8中修复。