【问题标题】:Precedence of &&, || and &, |&&, || 的优先级和 &, |
【发布时间】:2014-10-10 03:29:25
【问题描述】:

&| 运算符的优先级如何绑定到 &&|| 的优先级?我正在阅读 15.22

位运算符和逻辑运算符包括 AND 运算符 &、异或运算符 ^ 和异或运算符 |。

[...]

这些运算符的优先级不同,其中 & 的优先级最高 优先级和 |最低优先级。

但是在相应的子句中提到了&&|| 的优先级。例如,让我有条件:

boolean a = true;
boolean b = false
boolean c = true;
if ( a && b | c || b){
    //to do something
}

你能用例子解释一下前面的内容吗? 我想看看标准中的参考资料。

【问题讨论】:

  • 这不清楚。 are ~1 billion webpages 上面有 Java 运算符优先级表;有什么问题?
  • @OliCharlesworth 这个问题是正式的解释,仅使用 JLS。
  • 所以你不想要“一个例子”?无论如何,JLS 给出的语法定义暗示了优先级。 (“ExclusiveOrExpression:ExclusiveOrExpression ^ AndExpression”等等……)
  • 不是您问题的直接答案,但不要根据优先规则编写代码。编写可读的代码,用括号括起来显示您的意图的操作。老实说,我不记得任何语言的所有规则,我发现不使用括号的代码令人沮丧(如果不是可怕的话)。
  • +1,对于这个问题,因为仅从 JLS 中获取这些信息非常困难(尽管这对大多数程序员没有实际意义,除了那些正在编写编译器的人...... )

标签: java language-lawyer bitwise-operators


【解决方案1】:

JLS 的15.2 Forms of Expressions 部分说:

运算符之间的优先级由语法产生式的层次结构管理。

这意味着优先级的实际定义有些隐藏。 Java 教程中的Operators 页面很好地列出了它们,但这不是您所要求的。在18. Syntax, in the JLS 7 部分,也有一个不错的列表。但是对于 Java 8,这个列表不再明确给出。

相反,优先级只能从语法本身派生出来,当然仍然指定,现在在 19. Syntax, in the JLS 8 部分。

对于您发布的示例:

if (a && b | c || b) { ... }

第一个匹配规则将是

IfThenStatement:
    if ( Expression ) Statement

然后,括号的内部将根据规则匹配ExpressionAssignmentExpressionConditionalExpressionConditionalOrExpression

Expression:
    LambdaExpression
    AssignmentExpression

AssignmentExpression:
    ConditionalExpression
    Assignment

ConditionalExpression:
    ConditionalOrExpression
    ConditionalOrExpression ? Expression : ConditionalExpression

ConditionalOrExpression:
    ConditionalAndExpression
    ConditionalOrExpression || ConditionalAndExpression

此时,您将拥有“解析树”

            ||
           /  \
a && b | c      b

右边的分支b会通过

的定义被整条链匹配
ConditionalAndExpression
InclusiveOrExpression
ExclusiveOrExpression
AndExpression
EqualityExpression
RelationalExpression
ShiftExpression
AdditiveExpression
MultiplicativeExpression
UnaryExpression
UnaryExpressionNotPlusMinus
PostfixExpression
ExpressionName 
Identifier

Identifierb)。

将匹配左分支a && b | c

ConditionalOrExpression:
    ConditionalAndExpression
    ConditionalOrExpression || ConditionalAndExpression

ConditionalAndExpression:
    InclusiveOrExpression
    ConditionalAndExpression && InclusiveOrExpression

此时解析树为

            ||
           /  \
          /    \
         /      \
        &&       b
       /  \
      /    \
     a    b | c

a 将被标识为 Identifier,与 b 相同。剩下的b | c会直接匹配

InclusiveOrExpression:
    ExclusiveOrExpression
    InclusiveOrExpression | ExclusiveOrExpression

标识符 bc 将像以前一样匹配。

最终的解析树将是

            ||
           /  \
          /    \
         /      \
        &&       b
       /  \
      /    \
     a      |
           / \
          /   \
         b     c

(如果我没记错的话。那是相当复杂的......)

【讨论】:

  • 是的,这正是我所寻找的。形式化解释,仅使用 JLS。谢谢。
【解决方案2】:

这是优先顺序(从高到低):

bitwise AND             &
bitwise exclusive OR    ^
bitwise inclusive OR    |
logical AND            &&
logical OR             ||

(Source)

因此if ( a && b | c || b) 等同于:

if ( (a && (b | c)) || b)

【讨论】:

  • 你的来源不是 JLS。
  • @DmitryFucintv 它来自甲骨文。这应该足够了。
  • @DmitryFucintv:您是否发布了一个关于实际问题的 SO 问题,而不是针对规范进行语言律师?
  • @DmitryFucintv:请随意阅读规格!但 SO 是针对实际的、实际的问题的。没有数百个关于语言标准细节的问题。
  • @OliCharlesworth 好吧,公平地说,我不时喜欢这些细节......(但不是在这里,它几乎没有/没有增加价值)
【解决方案3】:

规范中没有说明优先顺序,但它来自 BNF 语法规则

ConditionalAndExpression:
  InclusiveOrExpression
  ConditionalAndExpression && InclusiveOrExpression

ConditionalOrExpression:
  ConditionalAndExpression
  ConditionalOrExpression || ConditionalAndExpression

这些规则表明x && y || z 将解析为(x && y) || z(一个包含ConditionalAndExpression 作为其左操作数的ConditionalOrExpression)而不是x && (y || z)(这将需要and 表达式以允许将or 表达式作为操作数,这它不会没有括号)。

因此&&|| 绑定得更紧密。

你可以用同样的方式构造优先表的其余部分,通过跟踪InclusiveOrExpression的定义等等。

【讨论】:

  • 相当准确的答案。谢谢。
【解决方案4】:

18.1 语法

InfixOp:
        ||
        &&
        |
        ^
        &
        ==
        !=
        <
        >
        <=
        >=
        <<
        >>
        >>>
        +
        -
        *
        /
        %

运算符在此处按从低到高的优先级列出(&amp; 高于 |,如您在 15.22 中找到的示例)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 2017-11-08
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多