问题
JLS:
The lowest precedence operator is the arrow of a lambda expression (->), followed by the assignment operators.
Followed in which direction (increasing priority, decreasing priority)? - "followed" means assignment has higher priority or lower priority (with respect to arrow operator)? I guess, in increasing, because "lowest" (for arrow) means absolutely lowest.
As I understand, arrow (->) should be at the very bottom of this Princeton operator precedence table (that is below all assignment operators), thus arrow (->) having 0 (zero) priority Level (as per that table).
Am I correct in my understanding?
ExamTray seems to say that arrow priority is at least same as assignment... Plus clarified that arrow associativity is Left->To->Right (unlike assignment). I didn't find any JLS quote for arrow associativity.
I always used to think that assignment priority is principally lowest for a reason.
回答1:
Note the sentence preceding the quoted JLS text:
Precedence among operators is managed by a hierarchy of grammar productions.
The grammar of the Java language determines which constructs are possible and implicitly, the operator precedence.
Even the princeton table you’ve linked states:
There is no explicit operator precedence table in the Java Language Specification. Different tables on the web and in textbooks disagree in some minor ways.
So, the grammar of the Java language doesn’t allow lambda expressions to the left of an assignment operator and likewise, doesn’t allow assignments to the left of the ->
. So there’s no ambiguity between these operators possible and the precedence rule, though explicitly stated in the JLS, becomes meaningless.
This allows to compile, e.g. such a gem, without ambiguity:
static Consumer<String> C;
static String S;
public static void main(String[] args)
{
Runnable r;
r = () -> C = s -> S = s;
}
回答2:
First, let's explain the practical issue here.
Assuming you have a definition like
IntUnaryOperator op;
The following is syntactically accepted, and works as expected:
op = x -> x;
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;
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;
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
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
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
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.
来源:https://stackoverflow.com/questions/59068702/arrow-operator-precedence-priority-is-lowest-or-priority-of-assignment-com