Thinking in "++i" and "i++"

i++ 与++i是咱们在操做临时变量常常用到的操做符,可是,不当心又会把本身搞的很糊涂。终其缘由,仍是没有搞清楚其本质 。 java

i++:书上所说,当++位于变量后时,表示为在该变量调用 后将其加1 即i = i+1; spa

++i:在调用i之间先将i加1 再进行应用 。 索引

可是,这里有一个例子: 内存

int i = 1; get

i = i++; 编译

System.out.println(i); 变量

问:这时的i值是多少? 原理

刚开始,有不少人会认为是2;他们给出的理由是,i在定义时便进行了初始化--->1;而后进行i = i++ 运算,此时的i仍是1,可是随即进行i++操做,修改了原先的i值,即i的值为2,因此应该输出2。 方法

其实否则,本人理解以下: im

int i = 1; i = i++;这段代码与下面代码相同:

int i = 1;

int temp = i;

i ++;

i = temp;

JVM会给i分辟一块新的内存,在进行最后的赋值操做时又将这块新内存中的值给它。也就是说,i的值仍是本身之前的值,没有变。经过javap -c 反编译即可看到具体信息:

从主方法内能够看到执行过程:

iconst_1:将常数1压栈,栈内容【1】;

istore_1:将栈顶元素弹出,也就是1(i),保存到局部变量区索引为1的地方,栈内容【】;

iloadt_1:将局部变量区索引为1的值压入栈,栈内容【1】

iinc    1,1:将局部变量变量区索引为1(i)的值加1,此时栈内容为【2】;

istore_1:将栈顶元素弹出,存入局部变量区索引为1的地方,此时i又变成了1,栈内容为【】

getstatic     #2:获取常量池中索引为2所表示的类变量,也就是System.out,栈内容【】

iload_1:将局部变量区索引为1的值(也就是i)压入栈,栈内容【1】

invokevirtual  #3:调用常量池中索引为3的方法---->System.out.println

return: 返回main方法

综上,i的值是没有变化 的,仍是先前初始化赋给的值 ----->1;

那行,咱们再改改,看下段代码执行结果是什么:

int i = 1;

int j = 0;

j = i++;

System.out.println(i);  //这时,i的值 为2;为何呢?

解释以下:

栈首先对i进行压栈,后弹出,放在局部变量区中(索引为1);而后对j进行压栈,再弹出存储在局部变量区(索引为2);

接着,栈将局部变量区中索引为1的值i进行压栈,将局部变量区索引为1的值进行加1操做--->i=2;

在对i进行加1操做后,再将栈顶元素弹出(记住,此时的栈顶元素i值 为1),保存到局部变量区索引为2的地方(即对j进行加1操做),j--->1;

调用System.out

将局部变量区中索引为1的值压入栈中,此时栈顶元素为2;

调用常量池中System.out.println方法

return;

因此,此时i的值变为了2 。

总结,i++与++i对于每 一我的来讲,其逻辑是不难的。难点就在于对堆栈原理 理解的不够深。

相关文章
相关标签/搜索