【问题标题】:Arrow (->) operator precedence/priority is lowest, or priority of assignment/combined assignment is lowest?箭头 (->) 运算符优先级/优先级最低,还是赋值/组合赋值的优先级最低?
【发布时间】:2020-03-22 22:06:28
【问题描述】:

JLS:

最低优先级运算符是 lambda 表达式的箭头 (->)后跟是赋值运算符。

遵循哪个方向(增加优先级,降低优先级)? - “followed”意味着分配具有更高的优先级或更低的优先级(相对于箭头运算符)?我想,在增加,因为“最低”(箭头)意味着绝对最低。

据我了解,箭头 (->) 应位于此 Princeton 运算符优先级表的最底部(即在所有赋值运算符之下),因此箭头 (->) 具有 0(零)优先级(如根据该表)。

我的理解正确吗?

ExamTray 似乎说箭头优先级至少与赋值相同...另外澄清箭头关联性是 Left->To->Right (与赋值不同)。我没有找到任何关于箭头关联性的 JLS 引用。

我一直认为分配优先级最低是有原因的。

【问题讨论】:

  • The lowest precedence operator is the arrow of a lambda expression.
  • 是的,你的理解是正确的。
  • 如果-> 是最低的est,则赋值运算符的优先级不能低于er
  • IntFunction fo = a->b->a-b; // in test 通常暗示 -> 的优先级/关联性。所以我决定澄清 -> 优先级/关联性在整个优先级/关联性表中的位置,因为我不确定。
  • @glglgl 你的IntUnaryOperator op; op = x -> x; 例子很有趣。也许(op = x) -> x 不被考虑,因为op = x 不是LambdaParameters 生产的有效实例?

标签: java java-8 language-lawyer operator-precedence specifications


【解决方案1】:

注意引用JLS text之前的句子:

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

Java 语言的语法决定了哪些构造是可能的,并且隐含地确定了运算符的优先级。

即使是您链接的 princeton table 状态:

Java 语言规范中没有明确的运算符优先级表。网络和教科书中的不同表格在一些小方面存在分歧。

因此,Java 语言的语法不允许将 lambda 表达式放在赋值运算符的左侧,同样,也不允许在 -> 的左侧进行赋值。因此,这些运算符之间没有歧义,并且优先规则虽然在 JLS 中明确说明,但变得毫无意义。

这允许编译,例如这样的宝石,毫不含糊:

static Consumer<String> C;
static String S;
public static void main(String[] args)
{
  Runnable r;
  r = () -> C = s -> S = s;
}

【讨论】:

    【解决方案2】:

    首先,让我们在这里解释一下实际问题。

    假设你有这样的定义

    IntUnaryOperator op;
    

    以下内容在语法上被接受,并按预期工作:

    op = x -> x;
    

    也就是说,我们将int 上的恒等函数分配给op 变量。但是如果= 具有更高的优先级,我们希望Java 将其解释为

    (op = x) -> x;
    

    这在语法上无效,因此应该是编译错误。因此,在实践中,赋值并不比箭头具有更高的优先级。

    但以下也可以(假设tint 类型的类/实例变量):

    op = x -> t = x;
    

    这将编译,如果应用该函数,则将操作数的值分配给 t 并返回它。

    这意味着箭头的优先级不高于赋值t = x。否则它会被解释为

    op = ( x -> t ) = x
    

    显然,这不是发生的事情。

    所以看起来这些操作具有相同的优先级。更重要的是,它们是右结合的。 JLS chapter 19 的语法暗示了这一点:

    Expression:
      LambdaExpression
      AssignmentExpression
    
    LambdaExpression:
      LambdaParameters -> LambdaBody
    
    ...
    
    LambdaBody:
      Expression
      Block
    

    所以 lambda 主体的右侧让我们回到 Expression,这意味着我们可以在其中有一个(更高优先级的)lambda,或者在其中有一个(更高优先级的)赋值。我所说的“更高优先级”的意思是,您越深入了解产生式规则,就会越早评估表达式。

    赋值运算符也是如此:

    AssignmentExpression:
      ConditionalExpression
      Assignment
    
    Assignment:
      LeftHandSide AssignmentOperator Expression
    

    再一次,赋值的右侧让我们回到Expression,所以我们可以在那里有一个 lambda 表达式或一个赋值。

    因此,语法不依赖于 JLS 文本,而是为我们提供了对情况的明确描述。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-27
      • 2015-08-24
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      • 2018-08-14
      相关资源
      最近更新 更多