[英]Assigning a variable, what actually happens, Java
In the following example what actually happens? 在下面的例子中实际发生了什么?
int a = 1;
a += (a = 2);
The output is 3, however I wanted to know what actually happens under the covers. 输出是3,但我想知道封面下究竟发生了什么。 For example i know that parentheses have higher priority to
+
so happening first (a = 2) the expression should become a = 2 + 2
. 例如,我知道括号的优先级高于
+
所以首先发生(a = 2)表达式应该变为a = 2 + 2
。 At runtime first the expression within parentheses should be executed and then a becomes 2. It seems that the first a
on the left to +
gets "loaded" before of (a = 2)
and this last expression does not seem to override the previous loading. 在运行时会首先括号内的表达式应该被执行,然后变成2.看来,第一次
a
在左边+
被“装”的前(a = 2)
这最后的表达似乎并没有覆盖以前装载。 In other words I am quite confused to what exactly happens behind the scenes. 换句话说,我对幕后究竟发生了什么感到困惑。
If anybody knows, thanks a lot in advance. 如果有人知道,请提前多多感谢。
From the JLS section §15.26.2 Compound Assignment Operators : 来自JLS 部分§15.26.2复合赋值运算符 :
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
形式E1 op = E2的复合赋值表达式等效于E1 =(T)((E1)op(E2)),其中T是E1的类型,除了E1仅被评估一次。
So for your example we have: 因此,对于您的示例,我们有:
a = (a) + (a = 2)
With the expression evaluated left to right. 表达式从左到右评估。 Hence the output of 3
因此输出3
See the referenced example 15.7.1-2 from http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7.1 , which is almost identical to the example you provided. 请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7.1中引用的示例15.7.1-2 ,这与您的示例几乎相同提供。 In particular:
特别是:
If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.
如果运算符是复合赋值运算符(第15.26.2节),则对左侧操作数的计算包括记住左侧操作数表示的变量并获取并保存该变量的值以用于隐含的二进制操作。
Because of this precedence, the left hand of the += is evaluated first. 由于这个优先级,首先评估+ =的左手。
It might be confusing to you because of the parentheses, but note the section on parenthesis evaluation: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7.3 , and in particular: 由于括号,您可能会感到困惑,但请注意括号评估部分: http : //docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7.3 ,特别是:
The Java programming language respects the order of evaluation indicated explicitly by parentheses and implicitly by operator precedence.
Java编程语言遵循由括号显式指示的评估顺序,并且隐含地由运算符优先级指示。
In this case, the implicit precedence set by the += operator indicates that the left hand operand will be remembered per the spec. 在这种情况下,+ =运算符设置的隐式优先级表示将根据规范记住左侧操作数。 While it's true that assignment operators, including "+=" have lowest precedence, the spec for += indicates that the left-hand operand will be remembered per 15.26.2.
虽然包括“+ =”在内的赋值运算符具有最低优先级,但+ =的规范表示将按15.26.2记住左侧操作数。
Let's take a look at the bytecode of the following program: 我们来看看以下程序的字节码:
package A;
public class Test
{
public static void main(String[] args)
{
int a = 1;
a += (a = 2);
}
}
We just need to run this command: 我们只需要运行这个命令:
javap -c Test.class
to get the following bytecode: 获取以下字节码:
public class A.Test {
public A.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iload_1
3: iconst_2
4: dup
5: istore_1
6: iadd
7: istore_1
8: return
}
We will just focus on the two lines inside the main method: 我们将只关注main方法中的两行:
int a = 1;
a += (a = 2);
[ int a = 1;
[
int a = 1;
begins here] 从这里开始]
0: iconst_1
1
onto the stack. 1
推入堆栈。 -------------
| |
-------------
| |
-------------
| 1 |
-------------
STACK
1: istore_1
variable 1
( variable 1
represents a
) variable 1
( variable 1
表示a
) -------------
| | variable 1
------------- --------------
| | | 1 |
------------- --------------
| |
-------------
STACK
[ int a = 1;
[
int a = 1;
finishes here] 在这里完成]
[ a += (a = 2);
[
a += (a = 2);
begins here] 从这里开始]
2: iload_1
variable 1
and pushes it onto the stack. variable 1
加载一个int值并将其推送到堆栈。 -------------
| | variable 1
------------- --------------
| | | |
------------- --------------
| 1 |
-------------
STACK
3: iconst_2
2
onto the stack. 2
推入堆栈。 -------------
| | variable 1
------------- --------------
| 2 | | |
------------- --------------
| 1 |
-------------
STACK
4: dup
-------------
| 2 | variable 1
------------- --------------
| 2 | | |
------------- --------------
| 1 |
-------------
STACK
5: istore_1
variable 1
. variable 1
。 -------------
| | variable 1
------------- --------------
| 2 | | 2 |
------------- --------------
| 1 |
-------------
STACK
6: iadd
-------------
| | variable 1
------------- --------------
| | | 2 |
------------- --------------
| 3 |
-------------
STACK
7: istore_1
variable 1
. variable 1
。 -------------
| | variable 1
------------- --------------
| | | 3 |
------------- --------------
| |
-------------
STACK
[ a += (a = 2);
[
a += (a = 2);
finishes here] 在这里完成]
8: return
a = a + (a = 2)
is done through several operations. a = a + (a = 2)
通过几次操作完成。 2: iload_1
is executed as first command of a += (a = 2);
2: iload_1
执行2: iload_1
作为a += (a = 2);
第一个命令a += (a = 2);
which reads the first operand of the equation a = a + (a = 2)
and pushes onto the stack. 它读取等式
a = a + (a = 2)
的第一个操作数并推入堆栈。
Next, 3: iconst_2
and 4: dup
are executed which basically push int 2
twice onto the stack; 接下来,执行
3: iconst_2
和4: dup
,基本上将int 2
两次推入堆栈; one for loading it to a
and the other as the second operand. 一个用于将其加载到
a
,另一个用作第二个操作数。 After that, 5: istore_1
is executed which is loading 2
into a
( a = 2
). 之后,执行
5: istore_1
,其将2
加载到a
( a = 2
)中。
Finally, 6: iadd
and 7: istore_1
are executed where 6: iadd
adds the first operand and the second operand and pushes the result onto the stack, and 7: istore_1
pops the result and loads it into a
. 最后,
6: iadd
和7: istore_1
被执行,其中6: iadd
添加第一个操作数和第二个操作数并将结果推送到堆栈上, 7: istore_1
弹出结果并将其加载到a
。
For simplicity, let's have a quick look at this code: 为简单起见,我们快速浏览一下这段代码:
int a = 1;
int b = 3;
a += b;
and here is its bytecode: 这是它的字节码:
public class A.Test {
public A.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_3
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_1
8: return
}
As you can see, it simply does the following: 如您所见,它只是执行以下操作:
1
into a
. 1
加载到a
。 3
into b
. 3
加载到b
。 a
then b
onto the stack. a
然后b
推到堆栈上。 a
. a
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.