JLS:
最低优先级运算符是 lambda 表达式的箭头 (->(, 后跟赋值运算符。
遵循哪个方向(增加优先级,降低优先级(? - "遵循"表示分配具有较高优先级或较低优先级(相对于箭头运算符(?我想,在增加中,因为"最低"(箭头(意味着绝对最低。
据我了解,箭头 (->( 应该位于普林斯顿运算符优先级表的最底部(低于所有赋值运算符(,因此箭头 (->( 具有 0(零(优先级(根据该表(。
我的理解正确吗?
ExamTray似乎说箭头优先级至少与分配相同...加澄清箭头关联性是左>到>右(与分配不同(。我没有找到任何关于箭头关联性的 JLS 引用。
我一直认为分配优先级通常是最低的,这是有原因的。
注意引用的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;
}
首先,让我们在这里解释一下实际问题。
假设你有一个定义,
比如IntUnaryOperator op;
以下内容在语法上被接受,并按预期工作:
op = x -> x;
也就是说,我们在分配给op
变量int
上有一个恒等函数。但是,如果=
具有更高的优先级,我们希望Java将其解释为。
(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文本,而是为我们提供了对情况的明确描述。