箭头 (->) 运算符优先级/优先级最低,或者赋值/组合赋值的优先级最低?

JLS

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

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

据我所知,箭头(->)应该位于普林斯顿运算符优先级表的最底部(即在所有赋值运算符下方),因此箭头(->)具有0(零)优先级级别(根据该表)。

我的理解是否正确?

ExamTray似乎在说箭头优先级至少与分配相同......Plus 澄清了箭头关联性是左>到>右(与赋值不同)。我没有找到任何JLS引用箭头关联性。

我曾经认为分配优先级基本上是最低的,这是有原因的。


答案 1

请注意引用的JLS文本前面的句子:

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

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

甚至你链接的普林斯顿表格也说:

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;

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

(op = x) -> x;

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

但以下情况也是可以的(假设是一个类/实例变量的类型):tint

op = x -> t = x;

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

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

op = ( x -> t ) = x

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

因此,这些操作似乎具有相同的优先级。更重要的是,它们是右联想的。这从JLS第19章的语法中暗示:

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block

因此,lambda 主体的右侧将我们返回到 ,这意味着我们可以在其中具有(更高优先级)lambda,也可以在其中具有(更高优先级)赋值。我所说的“优先级更高”的意思是,你越深入地了解生产规则,表达式就会越早被计算出来。Expression

赋值运算符也是如此:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression

再一次,赋值的右侧将我们扔回 ,因此我们可以在那里有一个lambda表达式或赋值。Expression

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


推荐