为什么 n+++n 是有效的而 n++++n 不是?

15

在Java中,下面的表达式:

n+++n

似乎被视为等同于:

n++ + n
尽管+n是一个有效的一元运算符,比算术运算符+的优先级更高,在n + n中。编译器似乎假定该运算符不能是一元运算符,并解析表达式。

然而,表达式:

n++++n

尽管存在唯一的有效解决可能性,但编译不通过:

n++ + +n

++n+n 被指定为具有相同的优先级,那么为什么编译器在 n+++n 中解决看似的歧义时会偏向于算数运算符 +,而在 n++++n 中却不会这样做呢?


你应该包含相关的编译器错误。 - hyde
1
这可能与编译器有关,因为我在这里使用的是Eclipse,并且我刚刚在这里测试了n+++n语句,Eclipse告诉我它是无效的。 - Mauren
2
按照你的逻辑,++n 应该被解释为 +(+n),这将使 ++n 不可能。 - mvp
@Mauren 有趣的是,在Eclipse中进行测试时,当“n”最初设置为1时,它可以编译并给出结果3。 - Trevor Freeman
2
@Mauren n+++n; 不是一个有效的独立语句。问题在于表达式 n+++n。请尝试使用 x = n+++n; - John Kugelman
显示剩余4条评论
1个回答

18
文件首先按照最大匹配规则进行分词(转换为令牌序列)-始终获取最长的有效令牌。您的文本被转换为以下序列:
n ++ ++ n

这不是一个有效的表达式。

来自JLS §3.2

3.2. 词法翻译

使用以下三个词法翻译步骤,将原始Unicode字符流转换为一系列令牌:

  1. 将Unicode转义(§3.3)在原始Unicode字符流中翻译成相应的Unicode字符。形式为\uxxxx的Unicode转义,其中xxxx是十六进制值,表示其编码为xxxx的UTF-16代码单元。此翻译步骤允许任何程序仅使用ASCII字符表示。

  2. 将步骤1生成的Unicode流翻译为输入字符和行终止符(§3.4)的流。

  3. 将步骤2生成的输入字符和行终止符的流翻译为输入元素(§3.5)的序列,其中在丢弃空格(§3.6)和注释(§3.7)后,包括语法文法(§2.3)的终结符号(§3.5)。

在每个步骤中使用最长可能的翻译,即使结果最终不构成正确的程序,而另一种词法翻译会。

(因此,输入字符a--b被标记化(§3.5)为a, --, b,这不是任何语法正确的程序的一部分,即使标记化a, -, -, b可能是语法正确的程序的一部分。)


这个“规则”在哪里有文档记录?我们可以信赖这种行为吗? - dcaswell
1
@user814064 - 是的,我添加了Java 7规范中的文本和示例。在语言定义中,最大匹配是常见的。 - zch
谢谢!上面的人暗示这是编译器相关的行为。 - dcaswell
运算符的分词是从右到左吗?经过进一步测试,n+++n实际上被计算为n + ++n,这表明分词是从右到左进行的,尽管人们可能会认为分词是从左到右进行的。我在JLS中找不到任何关于这个问题的明确说明。 - Trevor Freeman
@increment1 - 它从左到右执行,但请注意 n++ +nn+ ++n 是等价的。两者都像这样:a = n; n++; b = n; return a + b; - zch
@zch 唉,没错...我在更新我的帖子时犯了一个错误。我把它改成了a+++b来验证哪个标记化被执行(++ +还是+ ++),不幸的是,我似乎误读了我的结果,实际上是++ +。感谢您详细的回答! - Trevor Freeman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接