a = (a++) * (a++) 在 Java 中给出奇怪的结果
我正在准备 OCPJP 考试,因此我必须了解 Java 的每一个奇怪的细节。这包括前置和后置增量运算符应用于变量的顺序。下面的代码给了我奇怪的结果:
int a = 3;
a = (a++) * (a++);
System.out.println(a); // 12
答案不应该是 11 吗?或者也许13?但不是12!
后续:
以下代码的结果是什么?
int a = 3;
a += (a++) * (a++);
System.out.println(a);
I'm studying for the OCPJP exam, and so I have to understand every little strange detail of Java. This includes the order in which the pre- and post-increment operators apply to variables. The following code is giving me strange results:
int a = 3;
a = (a++) * (a++);
System.out.println(a); // 12
Shouldn't the answer be 11? Or maybe 13? But not 12!
FOLLOW UP:
What is the result of the following code?
int a = 3;
a += (a++) * (a++);
System.out.println(a);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
之后第一个
a++
a
变成4。所以你有3 * 4 = 12
。(
a
在第二个a++
之后变为 5,但它被丢弃,因为赋值a =
会覆盖它)After the first
a++
a
becomes 4. So you have3 * 4 = 12
.(
a
becomes 5 after the 2nda++
, but that is discarded, because the assignmenta =
overrides it)您的陈述:
只是简写
并等同于任何这些更简单的表达式:
使用其中任何一个来代替。
Your statement:
is just a shorthand for
and is equivalent to any of those simpler epressions:
Use any of those instead.
a++
表示“a 的值,然后 a 加 1”。因此,当您运行第一个
a++
时,首先对其求值,并生成值 3。然后a
递增 1。然后是第二个a++
评价。a
产生值 4,然后再次递增(但这现在不重要了)所以这变成了
等于 12。
a++
means 'the value of a, and a is then incremented by 1'. So when you runthe first
a++
is evaluated first, and produces the value 3.a
is then incremented by 1. The seconda++
is then evaluated.a
produces the value of 4, and is then incremented again (but this doesn't matter now)So this turns into
which equals 12.
首先构建语法树:
从最外层元素开始并递归下降来评估它。对于每个元素,请执行以下操作:
+=
运算符很特殊:它会扩展为类似left = left + right
,但仅计算表达式left
一次。在右侧被评估为一个值之前,左侧仍然被评估为一个值(而不仅仅是一个变量)。这会导致:
+=
a
赋值的左侧。a
计算为将在加法中使用的值3
。*
a++
。这将返回3
的当前值并将a
设置为4
a++
。这将返回4
的当前值并将a
设置为5
+=< /代码>。左侧在第三步中被评估为
3
,右侧为12
。因此它将 3+12=15 分配给a
。a
的最终值为 15。这里需要注意的一件事是运算符优先级对计算顺序没有直接影响。它仅影响树的形式,从而间接影响顺序。但在树中的同级中,无论运算符优先级如何,求值始终是从左到右。
First build the syntax tree:
To evaluate it start with the outer most element and descent recursively. For each element do:
The
+=
operator is special: It gets expanded to something likeleft = left + right
, but only evaluating the expressionleft
once. Still the left side gets evaluated to a value(and not just a variable) before the right side gets evaluated to a value.This leads to:
+=
a
.a
to the value3
which will be used in the addition.*
a++
. This returns the current value of a3
and setsa
to4
a++
. This returns the current value of a4
and setsa
to5
+=
. The left side had been evaluated to3
in the third step and the right side is12
. So it assigns 3+12=15 toa
.a
is 15.One thing to note here is that operator precedence has no direct influence on evaluation order. It only affects the form of the tree, and thus indirectly the order. But among siblings in the tree the evaluation is always left-to right, regardless of operator precedence.
(a++)
是后增量,因此表达式的值为 3。(a++)
是后增量,因此表达式的值现在为 4。表达式计算从左侧开始向右。
(a++)
is a post increment, so value of expression is 3.(a++)
is post increment, so value of expression is now 4.Expression evaluation is happening from left to right.
每次使用 a++ 时,都会对 a 进行后递增。这意味着第一个 a++ 的计算结果为 3,第二个 a++ 的计算结果为 4。3 * 4 = 12。
Each time the you use a++, you're post-incrementing a. That means the first a++ evaluates to 3 and the second evaluates to 4. 3 * 4 = 12.
人们普遍缺乏对操作员如何工作的了解。老实说,每个运算符都是语法糖。
您所要做的就是了解每个操作员背后实际发生的事情。假设如下:
然后可以使用这些概括重写复合运算符(为了简单起见,请忽略返回类型):
您可以重写示例:
as
可以使用多个变量进行拆分:
这样肯定更冗长,但是很明显,您永远不想在一行上执行两个以上的操作。
There is a general lack of understanding about how operators work. Honestly, every operator is syntactic sugar.
All you have to do is understand what is actually happening behind every operator. Assume the following:
Compound operators can then be rewritten using these generalizations (please ignore the return types for the sake of simplicity):
You can rewrite your example:
as
Which can be split out using multiple variables:
It's certainly more verbose that way, but it immediately becomes apparent that you never want to perform more than two operations on a single line.
如果是:,
则我们得到的输出为 12。
如果是:,
这里要注意的要点是,在这种情况下,编译器从左到右求解,并且
在后增量的情况下,在计算中使用增量之前的值,并且当我们从左向右移动时,使用增量值。
In case of :
hence we get output as 12.
In case of :
Main point to note here is that in this case compiler is solving from left to right and
in case of post increment, value before increment is used in calculation and as we move from left to right incremented value is used.
(a++)
表示返回a
并递增,所以(a++) * (a++)
表示 3 * 4(a++)
means returna
and increment, so(a++) * (a++)
means 3 * 4这是 java 代码:
这是字节码:
这是发生的情况:
将 3 压入堆栈,然后从堆栈中弹出 3 并将其存储在 a 中。
现在 a = 3 并且堆栈为空。
现在,它将“a”(3) 中的值推入堆栈,然后递增 a(3 -> 4)。
所以现在“a”等于“4”,堆栈等于{3}。
然后它再次加载“a”(4),推入堆栈并递增“a”。
现在“a”等于 5,堆栈等于 {4,3}
所以它最终从堆栈中弹出前两个值(4 和 3),相乘并将其存储回堆栈(12)。
现在“a”等于 5,堆栈等于 12。
最后从堆栈中弹出 12 并存储在 a 处。
田田!
Here is the java code:
Here is the bytecode:
Here is what happens:
Pushes 3 into the stack then pops 3 from the stack and stores it at a.
Now a = 3 and the stack is empty.
Now it pushes the value from "a" (3) into the stack, and then increments a(3 -> 4).
So now "a" equals "4" the stack equals {3}.
Then it loads "a" again (4), pushes into the stack and increments "a".
Now "a" equals 5 and the stack equals {4,3}
So it finally pops the fisrt two values from the stack (4 and 3), multiplies and stores it back into the stack (12).
Now "a" equals 5 and the stack equals 12.
Finally is pops 12 from the stack and stores at a.
TADA!
现在是 12 点。
表达式从左侧开始计算。确实如此:
计算第一部分 (3++) 后,a 为 4,因此在下一部分中,a = 3*4 = 12。
请注意,最后一个后递增 (4++) 被执行,但没有任何效果,因为在此之后为 a 分配了值 12。
It is 12.
The expression starts evaluating from left. So it does:
Once the first part (3++) is evaluated, a is 4, so in the next part, it does a = 3*4 = 12.
Note that the last post-increment (4++) is executed but has no effect since a is assigned with the value 12 after this.
示例 1
示例 2
只是为了确定在哪里放置
++
表达式,该表达式会根据位置更改值。Example 1
Example 2
Just to make sure where to put
++
expression which changes the value based on the location.每个人都清楚地解释了第一个表达式,以及为什么 a 的值为 12。
对于接下来的问题,答案对于不经意的观察者来说是完全显而易见的:
17
Everyone has clearly explained the first expression, and why the value of a is 12.
For the follow on question, the answer is totally obvious to the casual observer:
17
前&前缀后增量的优先级高于乘法运算符。因此表达式的计算结果为 3*4。
Pre & post-prefix increments have a higher precedence than the multiplication operator. hence the expression is evaluated as 3*4.
如果您使用 a++ ,则下次使用 a 时,它会增加 1。所以你的所作所为
If you use a++ the next time you use a it is incremented by one. So your doing