++i和i++仅仅是先加1和后加1的区别吗?

关于前置++与后置++的差异,这彷佛再熟悉不过了。前置++ 是先将变量的值加1,而后使用加1后的值参与运算。然后置++ 是先使用该值参与运算,而后再将该值加1。java

没错,关于两者之间的区别,的确能够这么认为,而且按照上面的方法操做,运算中也基本不会有什么错误。可是若是我告诉你,后置++ 其实与前置++同样,在参与运算以前都会将变量加1,你会信吗?post

哈哈,鬼才信呢,那我告诉你这是真的.....spa

public class PreAndPostPlusDemo {
   public static void main(String[] args) {
       int i = 15;
       prePlus1(i);
       prePlus2(i);
       prePlus3(i);
       prePlus4(i);
  }

   private static void prePlus1(int i) {
       int j = ++i;
       System.out.println("prePlus1:i=" + i + ",j=" + j);
  }

   private static void prePlus2(int i) {
       i = ++i;
       System.out.println("prePlus2:i=" + i);
  }

   private static void prePlus3(int i) {
       int j = i++;
       System.out.println("prePlus3:i=" + i + ",j=" + j);
  }

   private static void prePlus4(int i) {
       i = i++;
       System.out.println("prePlus4:i=" + i);
  }
}

程序并不复杂,就是使用前置++和后置++。运行结果以下:翻译

prePlus1:i=16,j=16
prePlus2:i=16
prePlus3:i=16,j=15
prePlus4:i=15

前三个方法输出没什么,属于正常,也是你们所能接受的。那么第四个方法怎么就输出 i=15呢?code

为何会是15呢?按照通俗的看法,虽而后置++是先参与运算,而后再将值加1,可是执行对自身的赋值运算后,该值也加1,变成16才是呀。何况,后置++对其余变量j赋值后,i自身也加1了,string

prePlus3:i=16,j=15it

为何对本身赋值后,结果就不同呢?编译

实际上,不论是前置++仍是后置++,都是先将变量的值加1.,而后才继续计算的,,两者之间真正的区别是:前置++是将变量的值加1后,使用增值后的变量进行运算的,然后置++是首先将变量赋值给一个临时变量,接下来对变量的值加1,而后使用临时变量进行运算,从效果上来说,假设有以下程序片断:class

int i=2;
int j=++i*30;

那么第二行代码就至关于变量

i+=1; //将i加1,变成3
j=i*30;//而后使用3*30,则j的结果就是90

代码再改一下,改为后置++

int i=2;
int j=i++ *30

那么第二行代码就至关于

int temp=i;//将i变量值赋给一个temp的临时变量,即temp=2
i+=1;     //将i加1,i值变成3
j=temp*30; //使用临时变量Temp进行运算,j的结果为60

进一步探索

接下来咱们来研究一下前置++与后置++的区别,为了能更好的说明该问题,先列出一个很是简单的程序:

public class DeepPlus {
   void post() {
       int i = 0;
       int j = i++;
  }
   void pre() {
       int i = 0;
       int j = ++i;
  }
}

找到DeepPlus.class的目录 下,使用命令:

javap -c  DeepPlus

其中javap是翻译命令,-c为显示代码反编译后的伪指令。输出:

640?wx_fmt=png

咱们能够看到两个方法post和pre:

细说post方法:

void post();
Code:
//将int类型常量0压入栈,即当前栈定值为int类型0
0: iconst_0
//从栈顶弹出一个int类型值,而后将该值存储在局部变量1中,这里局部变量1就是
//程序中的变量i,也就是将刚才压入栈的0弹出,赋值给变量i
//这两个指令至关于执行(int i=0;)
1: istore_1
//将局部变量1中存储的int类型值压入栈,即将i的值0压入栈,
//这在程序中就至关于将i的值赋给一个临时变量temp,此时temp的值为0
2: iload_1
//将局部变量1的值加1,也就是将i的值加1.在程序中这个至关于(i+=1;)
//此时,i的值为1
3: iinc          1, 1
//从栈顶弹出一个int类型值,而后将该值存储在局部变量2中,这里局部变量2就是
//程序中的变量j,也就是将刚刚入栈的i值0弹出(i压栈时值还没加1)
//赋值给变量j,在程序中至关于(j=temp)
6: istore_2
//返回
7: return

继续看pre方法

void pre();
Code:
//将int类型常量0压入栈,即当前栈顶值为int类型0
0: iconst_0
//从栈顶弹出一个int类型值,而后将该值存储在局部变量1中,
//这里局部变量就是程序中的变量i,也就是将刚刚入栈的0弹出
//赋值给变量i。
//这两天指令至关于执行(int i=0;)
1: istore_1
//将局部变量1的值加1.也就是将i的值加1.
//在程序中至关于(i+==1;)
//此时,i的值为1,注意,前置++在执行指令iinc的时候并无
//将i的值压入栈,也就是并无赋值给一个临时变量
2: iinc          1, 1
//将局部变量1中存储的int类型值压入栈,即将i的值1压入栈
5: iload_1
//从栈顶弹出一个int类型值,而后将该值存储在局部变量2中。这里的局部变量2就是
//程序中的变量j,也就是将刚刚入栈的i值1弹出(i压栈时值已经加1了)
//赋值给变量j。至关于(j=i)
6: istore_2
//返回
7: return

如今咱们已经从指令的级别分析完了两者之间的差别。

前置++直接将变量的值加1,而后使用这个变量的值。然后置++是先将变量的值压入栈(暂时保存起来),而后将变量的值加1,以后使用压栈时变量的值。

总结

  1. 前置++与后置++都是先将变量的值加1,而不是前置++先加1而后运算,,然后置++先运算再加1。

  2. 从代码上来讲,后置++先将变量赋给一个临时变量,而后将变量的值加1,接下来使用临时变量参与运算。

  3. 从指令上来讲,后置++在执行增值指令iinc前,先将变量的值压入栈,执行增值指令后,使用的是以前压入栈的值。

逆水行舟,不进则退!但愿你们都能踏踏实实地拥抱新技术!!!


● 

● 

● 

● 

● 

  640?wx_fmt=gif
你点的每一个在看,我都认真当成了喜欢你