天天看点

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

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

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

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

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呢?

为什么会是15呢?按照通俗的见解,虽然后置++是先参与运算,然后再将值加1,但是执行对自身的赋值运算后,该值也加1,变成16才是呀。况且,后置++对其他变量j赋值后,i自身也加1了,

prePlus3:i=16,j=15

为什么对自己赋值后,结果就不一样呢?

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

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为显示代码反编译后的伪指令。输出:

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

我们可以看到两个方法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前,先将变量的值压入栈,执行增值指令后,使用的是之前压入栈的值。
逆水行舟,不进则退!希望大家都能踏踏实实地拥抱新技术!!! 来自于公众号:Java后端技术栈