发布于 2019-11-27 12:17:56
注意引用的JLS文本前面的句子
运算符之间的优先级由语法产品的层次结构管理。
Java语言的语法决定了哪些构造是可能的,哪些是隐式的,操作符优先。
甚至连你所链接的普林斯顿桌也是如此:
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;
}
发布于 2019-11-27 12:09:00
首先,让我们在这里解释一下实际问题。
假设你有这样的定义
IntUnaryOperator op;
以下内容在语法上被接受,并按预期工作:
op = x -> x;
也就是说,我们在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主体的右侧将我们带回到Expression
,这意味着我们可以在其中包含一个(更高优先级) lambda,或者在其中分配一个(更高优先级)分配。我所说的“更高优先级”的意思是,越深入地研究生产规则,表达式就越早被评估。
赋值运算符也是如此:
AssignmentExpression:
ConditionalExpression
Assignment
Assignment:
LeftHandSide AssignmentOperator Expression
再一次,分配的右侧将我们抛回Expression
,这样我们就可以有lambda表达式或赋值了。
因此,语法没有依赖于JLS文本,而是给出了对情况的一个定义良好的描述。
https://stackoverflow.com/questions/59068702
复制相似问题