箭头(->)运算符的优先级/优先级最低,还是分配/组合分配的优先级最低?

Cod*_*ete 17 java specifications operator-precedence language-lawyer java-8

JLS

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

遵循哪个方向(增加优先级,减少优先级)?-“跟随”是指分配的优先级较高还是较低(相对于箭头运算符)?我猜想,这是因为“最低”(箭头)表示绝对最低。

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

我的理解正确吗?

ExamTray似乎说箭头优先级至少与分配相同。此外,还阐明了箭头的关联性是Left-> To-> Right(与分配不同)。我没有找到JLS的箭头关联性报价。

我一直认为分配优先级原则上最低。

Hol*_*ger 11

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

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

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

甚至您已链接的princeton表也指出:

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

因此,Java语言的语法不允许在赋值运算符的左侧使用lambda表达式,同样,也不允许在->。运算符的左侧进行赋值。因此,尽管这些操作符之间没有歧义,但优先规则(尽管在JLS中已明确指出)变得毫无意义。

这样可以毫无歧义地编译例如这样的gem:

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


Rea*_*tic 8

First, let's explain the practical issue here.

Assuming you have a definition like

IntUnaryOperator op;
Run Code Online (Sandbox Code Playgroud)

The following is syntactically accepted, and works as expected:

op = x -> x;
Run Code Online (Sandbox Code Playgroud)

That is, we have an identity function on int assigned to the op variable. But if = had a higher priority, we'd expect Java to interpret this as

(op = x) -> x;
Run Code Online (Sandbox Code Playgroud)

Which is not syntactically valid, thus should be a compile error. Hence, assignment does not, in practice, have higher precedence than the arrow.

But the following is also OK (assume t is a class/instance variable of type int):

op = x -> t = x;
Run Code Online (Sandbox Code Playgroud)

This compiles, and the function, if applied, assigns the value of the operand to t and also returns it.

This means that the arrow doesn't have higher precedence than the assignment t = x. Otherwise it would have been interpreted as

op = ( x -> t ) = x
Run Code Online (Sandbox Code Playgroud)

and clearly, this is not what happens.

So it seems that the operations have equal precedence. What's more, that they are right-associative. This is implied from the grammar at JLS chapter 19:

Expression:
  LambdaExpression
  AssignmentExpression

LambdaExpression:
  LambdaParameters -> LambdaBody

...

LambdaBody:
  Expression
  Block
Run Code Online (Sandbox Code Playgroud)

So the right side of the lambda body gets us back to Expression, which means we can either have a (higher priority) lambda inside it, or a (higher priority) assignment in it. What I mean by "higher priority" is that the deeper you go through the production rules, the earlier the expression will be evaluated.

The same is true for the assignment operator:

AssignmentExpression:
  ConditionalExpression
  Assignment

Assignment:
  LeftHandSide AssignmentOperator Expression
Run Code Online (Sandbox Code Playgroud)

Once again, the right side of the assignment throws us back to Expression, so we can have a lambda expression or an assignment there.

So rather than relying on the JLS text, the grammar gives us a well defined description of the situation.