根据http://introcs.cs.princeton.edu/java/11precedence/,后增量运算符的优先级高于加法运算符。
因此,对于以下代码:
int i = 1;
int j = i + i++;
System.out.println(j);
我原本以为分配给j的表达式将按如下方式进行评估(评估中每行为"步骤")
i + i++
i + (1) // do post-increment operator; returns 1, and makes i = 2
(2) + (1) // do addition operator. need to get the operand i, so do that.
3
但是当我尝试这个程序时,j的值是2 所以我很困惑。在表达式中,它是否用i的当前值替换表达式中的所有" i,甚至在触及i ++之前?
编辑:短语"评估顺序"这里的人使用,帮助我找到以下可能有用的stackoverflow答案:What are the rules for evaluation order in Java?。
编辑:我在下面的答案中做了最好的猜测。我仍然欢迎对它进行更正。
答案 0 :(得分:2)
答案 1 :(得分:0)
增量后 - 首先使用先前的变量值然后递增 预增量 - 首先增量,然后使用新的变量值。
+
这里首先用前面的i值i替换i,e 1再次int i = 1;
int j = i++ + ++i;
System.out.println(j);// 4
System.out.println(i);// 3
的旧值,所以j将变为2,然后i增加到2。
现在考虑一下这段代码
{{1}}
这里首先i增加(pre),所以我变成2然后我被替换i,ej = 2 + 2,现在j值将是4并且再次i增加(post)一个所以我这样做当前值为3。
答案 2 :(得分:0)
不要让自己被"优先级"误导。字。 本教程的主要内容是,在解析表达式方面,后增量运算符的绑定比加法更强。
如果我们明确括号,示例中的表达式将显示为(i + (i++))
,而不是((i + i)++)
。
这是什么优先级意味着:没有明确的括号,将它们隐含地放在后增量之前,然后围绕加法。
当表达式的组件成功分组后,将考虑评估规则。在这种情况下,正如Korolar指出的那样,JLS 15.7.1是要考虑的段落,(简单地说)指示了对加法运算的从左到右的评估。
答案 3 :(得分:0)
编辑:我不理解其他人完全给出的答案,但这是我对正在发生的事情的最好猜测。如果有人想纠正这个猜测,请这样做。
我最好的猜测: {(1}},其中a,b和c是变量,被制作成表达式树,其中优先级最低的运算符位于树的顶部:
a + b * c
现在,这个树的评估如下:+运算符得到评估。为此,它(递归地)评估左子树及其右子树,然后添加这些值。
完整的,这就是:
+
/ \
a *
/ \
b c
这就是 - addition operator gets evaluated.
it says "evaluate my left subtree, then my right subtree,
then add them together. i return that value"
- left subtree: is a. evaluate variable a into a value.
(that is, get the value of variable a.)
- right subtree: i'm a multiplication operator. to evaluate me,
evaluate my left subtree, then my right subtree, the nmultiply
them togeter. i return that value.
- left subtree: is variable b. evalute that.
- right subtree: is variable c. evaluate that.
首先完成评估,然后是a
,然后是b
,然后是c
,然后是b * c
在带有++ i东西的表达式中,同样的事情发生了。例如,对于a + (b * c)
,表达式树将如下所示:
++i + i++
其中(例如)preinc表示preincrement运算符(而preincrement运算符只取一个操作数:变量)。这里的区别在于,当需要对preinc作为其根的子树进行求值时,“评估preinc运算符树”并不意味着“用变量的值替换操作数中的变量”(它的方式)例如,2 + i),但它意味着“增加变量i中的值,然后preinc(i)的值是变量i中的新值。”
以类似的方式,赋值运算符=的工作方式与2 + i略有不同。
+
/ \
preinc postinc
| |
i i
这里的表达式树是
int j;
j = 3;
当需要对赋值运算符作为其根的树进行求值时,这意味着“左手操作符必须是变量 - 而不是值!然后评估正确的子树(我们希望它将它评估为value),然后将值放在右子树中左子树中的变量中。现在,=(j,3)返回的值是右子树中的值“。
有了这个猜测,我能够正确地为评估顺序的Java语言规范中的示例提供答案(链接是:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.7)。
也就是说,如果我绘制表达式树,我可以解决以下两个例子:
例如:
=
/ \
j 3
示例:
int i = 2;
int j = (i = 3) * i;
System.out.println(j);