首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >++i和i++仅仅是先加1和后加1的区别吗?

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

作者头像
田维常
发布于 2019-10-15 08:45:52
发布于 2019-10-15 08:45:52
1.8K00
代码可运行
举报
运行总次数:0
代码可运行

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
    }
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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,然后使用临时变量进行运算,从效果上来讲,假设有如下程序片段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int i=2;
int j=++i*30;

那么第二行代码就相当于

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
i+=1; //将i加1,变成3
j=i*30;//然后使用3*30,则j的结果就是90

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int i=2;
int j=i++ *30

那么第二行代码就相当于

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int temp=i;//将i变量值赋给一个temp的临时变量,即temp=2
i+=1;      //将i加1,i值变成3
j=temp*30; //使用临时变量Temp进行运算,j的结果为60

进一步探索

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DeepPlus {
    void post() {
        int i = 0;
        int j = i++;
    }
    void pre() {
        int i = 0;
        int j = ++i;
    }
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
javap -c  DeepPlus

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

我们可以看到两个方法post和pre:

细说post方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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前,先将变量的值压入栈,执行增值指令后,使用的是之前压入栈的值。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档