8

我正在研究 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

为什么会这样?

4

3 回答 3

6

由于+and +++(or -and --) 都是左结合的,+++j因此被评估为++(+j)。由于++只能应用于左值(即变量)而+j不是左值(变量),因此会出现编译错误。

不过,您可以使用括号来解决此问题:i = +(++j);.

于 2016-02-11T17:54:49.223 回答
2

编译器使用贪婪的从左到右选择标记。所以当它看到 时+--j,最长的合法令牌序列是+,因为+-不是合法令牌,所以它+作为第一个令牌。然后它查看下一个可以识别为令牌的最大事物,即--j. 所以结果是+ --j

因为---j它被--视为最长的有效令牌,然后-j是下一个有效令牌,并尝试将它们放在一起-- -j,正如@Mureinik 指出的那样,它们是无效的。

于 2016-02-11T18:29:24.183 回答
1

在编译器甚至知道存在哪些运算符之前,它必须解析它们。我可以看到 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

于 2016-02-11T18:29:49.490 回答