这是一个纯粹的理论问题,为了清楚起见,我不会正常编写这段代码。
为什么这个含糊不清的陈述是合法的
int a = 1, b = 2;
int c = a---b; // a=0, b=2, c=-1
(它被解释为a-- -b
)
这个人不是吗?
int c = a-----b;
第一个语句可以也被解释为a- --b
,而第二个语句显然只有一个逻辑解释a-- - --b
。
另一个好奇的人:
int c = a--- -b; // a=0, b=2, c=3
(int c = a----b;
不是
如何在Java中定义表达式解释?我试过搜索JLS,但还没有找到答案。
答案 0 :(得分:2)
要回答这个问题,我们必须看看Javas operators precendence。
这个例子的重要规则是:
expr--
Postfix运算符的优先级高于a-b
添加运算符。因此,a-----b
这样的表达式将按如下方式进行评估:((a--)--)-b
非法。
您可以在声明中使用大括号绕过这些规则:(a--)-(--b)
将是一份法律声明。
答案 1 :(得分:2)
要正确理解这一点,需要认识到所有现代编译器都有两个级别来识别源语言,词汇级别和句法级别。
词法级别(“词法分析器”)将源代码分成标记:文字(字符串/数字/字符),运算符,标识符和词法语法的其他元素。这些是编程语言的“单词”和“标点符号”。
语法级别(“解析器”)涉及将这些低级词汇标记解释为语法,通常由语法树表示。
词法分析器是需要知道令牌是“减号”令牌(-
)还是“减量”(--
)令牌的级别。 (减去令牌是一元还是二元减号,或者递减令牌是一个后置还是预递减令牌是在句法层面确定的)
优先级,从左到右,从右到左等事物只存在于句法层面。但是,a---b
是a -- - b
还是a - -- b
是否在词汇层面确定。
Java Language Specification section 3.2 "Lexical Translations"
中描述了为什么a---b
变为a -- - b
最长可能的翻译用于每一步,即使是 结果最终没有做出正确的计划而另一个 词汇翻译会。
因此形成了最长的词汇标记。
对于a---b
,它会使令牌a
,--
(最长)成为唯一可能的下一个令牌-
,然后是b
。
如果是a-----b
,则会将其翻译为a
,--
,--
,-
,b
,没有语法上的有效。
进一步引用:
词汇翻译过程分为3个步骤,在这种情况下,上述情况适用于本案例中的步骤3:
原始Unicode字符流被转换为序列 令牌,使用以下三个词汇翻译步骤,即 依次申请:
Unicode原始流中Unicode转义(§3.3)的转换 字符到相应的Unicode字符。一个Unicode转义 形式\ uxxxx,其中xxxx是十六进制值,表示 UTF-16代码单元,其编码为xxxx。此转换步骤允许 任何只用ASCII字符表示的程序。
将步骤1产生的Unicode流转换为 输入字符和行终止符流(§3.4)。
- 醇>
输入字符流和行终止符的转换 从第2步到输入元素(§3.5)的序列,其中, 在白色空间(§3.6)和注释(§3.7)被丢弃之后,包括 令牌(§3.5)是句法的终结符号 语法(§2.3)。
(“输入元素”是“令牌”)