我正在研究 Java 前缀运算符并遇到了这种行为
i = +--j //does not give an error
i = -++j //does not give an error
i = ---j //gives an error
i = +++j //gives an error
为什么会这样?
我正在研究 Java 前缀运算符并遇到了这种行为
i = +--j //does not give an error
i = -++j //does not give an error
i = ---j //gives an error
i = +++j //gives an error
为什么会这样?
由于+and +++(or -and --) 都是左结合的,+++j因此被评估为++(+j)。由于++只能应用于左值(即变量)而+j不是左值(变量),因此会出现编译错误。
不过,您可以使用括号来解决此问题:i = +(++j);.
编译器使用贪婪的从左到右选择标记。所以当它看到 时+--j,最长的合法令牌序列是+,因为+-不是合法令牌,所以它+作为第一个令牌。然后它查看下一个可以识别为令牌的最大事物,即--j. 所以结果是+ --j
因为---j它被--视为最长的有效令牌,然后-j是下一个有效令牌,并尝试将它们放在一起-- -j,正如@Mureinik 指出的那样,它们是无效的。
在编译器甚至知道存在哪些运算符之前,它必须解析它们。我可以看到 3 种可能的解析---j:
- - -j // 3 unary - operators-- -j // predecrement -- followed by unary -- --j // unary - followed by predecrement --with 的情况+++j是等价的,带有前置增量++和一元+替换。
为什么 Java 将其解释为--,-第二种情况,这是唯一在语法上无效的情况?编译器通常是贪婪的。 JLS 第 3.2 节规定:
使用以下三个词汇翻译步骤将原始 Unicode 字符流翻译成一系列标记,依次应用:
...
每一步都使用尽可能长的翻译,即使结果最终不会产生正确的程序,而另一个词汇翻译会。有一个例外:如果词法转换发生在类型上下文(第 4.11 节)中并且输入流有两个或多个连续的 > 字符后跟一个非 > 字符,那么每个 > 字符必须被转换为数值比较运算符 >.
(粗体强调我的)
编译器贪婪地看到两个-字符并立即声明它是--令牌,而不考虑接下来会出现第三个字符-。
这与运算符关联性甚至运算符优先级无关,与语法解析有关。
正如@Mureinik 已经提到的那样,正确放置澄清括号将迫使编译器正确解析它。但它通过将字符分解为不同的标记来实现这一点,而不是通过改变操作的优先级。
表达式-++j不受编译器贪婪的影响;-+ 不是有效的令牌,因此它被正确解析为令牌-后跟令牌++,对于表达式也是如此+--j。