首先,让我们在这里解释一下实际问题。
假设你有一个像这样的定义
IntUnaryOperator op;
以下内容在语法上被接受,并按预期工作:
op = x -> x;
也就是说,我们有一个分配给变量的恒等函数。但是,如果具有更高的优先级,我们希望Java将其解释为int
op
=
(op = x) -> x;
这在语法上无效,因此应该是编译错误。因此,在实践中,赋值的优先级并不高于箭头。
但以下情况也是可以的(假设是一个类/实例变量的类型):t
int
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文本,而是为我们提供了对情况的明确定义描述。