关于Java中的自增、自减运算符j=j++;

时间:2021-09-28 17:24:08
 这几天要准备找实习了,临阵磨枪,不快也光,然后开始疯狂做题突击,遇到了这么一题

import java.util.*;
public class Test{
    public static void main(String[] args){
        int j=0;
        for (int i = 0; i < 100; i++){
            j = j++;
        }
        System.out.println(j);
    }
}

    问输出的结果是多少。我相信很多人和我一样第一反应应该是想到100。但是结果却是错误的,不敢相信,然后上机实践发现确实不对。这是为什么?结果又应该是多少呢?
    原来这是因为Java编译器使用了中间缓存变量的机制。j=j++;可以转换为如下写法:

temp = j;
j = j + 1;
j = temp;

    这是在Java程序员面试宝典中给出的答案,感觉很不理解,然后又上网开始查,发现 http://www.bitscn.com/plus/view.php?aid=20350这个解释就很容易理解了。
   像j=j++;这种赋值语句, Java编译器每次遇到自增、自减运算符的时候都会开辟一块新的内存空间来保存赋值之前j的值,就是前文介绍的缓存变量,然后再将这个换成变量的值赋给左边的变量。链接里面通过内存空间图的方式讲解的很清楚,这里就不重复了。
    所以本题的正确结果应该就是0。
    题目会做错从本质上来分析的话应该还是对自增、自减运算符没掌握好,究竟是先用原值进行计算再加1,还是先加1再进行运算是这类题目特别需要注意的陷阱。这题是先用j的原值进行计算,那就是j=0;之后应该还有一个自增语句,但是由于变量已经被覆盖了,貌似就可以忽略了。
    如果我们将赋值语句改为j = ++j;那会怎么样呢?现在应该是这么个流程

temp = j +1;
j = j + 1;
j = temp;

    如果是这样的话,输出应该就是100了。
    所以再对自增、自减运算符的变量进行赋值时都需要特别注意。借用别人的一句话:“如果在程序中只输入i++就不会出现这个方面的问题,所以大家在以后的程序中如果使用到i=i++的时候要格外小心,一般只需要用i++就不会有问题了。”

6 个解决方案

#1


扫盲了                                   关于Java中的自增、自减运算符j=j++;

#2


学习了 关于Java中的自增、自减运算符j=j++;
不过,一般不论是C还是Java,都不推荐这样使用自增

#3


这些面试题都是这样 看似很难理解 很炫 但其实实际工作都不可能用到这种个性的用法

#4


我也试过,同样很不理解,但是我想到了另一个问题。
你在for循环中用的是i++,如果按照上面的理解,i永远是0,永远到不了100的上限退出循环,那么for循环岂不是永远执行下去了?还是说for循环内部的算法和这个稍有不同?

#5


引用 4 楼 litong534 的回复:
我也试过,同样很不理解,但是我想到了另一个问题。
你在for循环中用的是i++,如果按照上面的理解,i永远是0,永远到不了100的上限退出循环,那么for循环岂不是永远执行下去了?还是说for循环内部的算法和这个稍有不同?

不是的,在遇到自增自减运算符以后会开拓一个新的内存空间,来保存i之前的值,由于没有发生赋值,则新保存的i值(i的旧值)就没用了,下一步直接舍弃,然后i本身是完成了加1运算的。

#6


引用 4 楼 litong534 的回复:
我也试过,同样很不理解,但是我想到了另一个问题。
你在for循环中用的是i++,如果按照上面的理解,i永远是0,永远到不了100的上限退出循环,那么for循环岂不是永远执行下去了?还是说for循环内部的算法和这个稍有不同?


int j=0; int i = 0;
int x = j++ + j++ + ++j;
int y = i++ + i++ + i++;
System.out.println("x:"+x+"y:"+y);

这两个赋值语句,x= 0(j++)+ 1(j++)+3(++j) = 4;
y = 0(i++)+1(i++)+2(i++) = 3;
从另一个角度来看,i++操作具有一个延时效果,在本次计算的时候还是i原来的值,在下一次使用i值进行计算就是加1的结果;而++i不同,先在i原值的基础上加1,然后用更新后的i值参与计算。
上面对x赋值时,最后一个++j,上一步更新后的j为2,在此基础上+1参与计算记为3,所以最后结果为4;
对y赋值时,最后一个i++,用i的原值进行计算,之后i值更新,所以为3.

#1


扫盲了                                   关于Java中的自增、自减运算符j=j++;

#2


学习了 关于Java中的自增、自减运算符j=j++;
不过,一般不论是C还是Java,都不推荐这样使用自增

#3


这些面试题都是这样 看似很难理解 很炫 但其实实际工作都不可能用到这种个性的用法

#4


我也试过,同样很不理解,但是我想到了另一个问题。
你在for循环中用的是i++,如果按照上面的理解,i永远是0,永远到不了100的上限退出循环,那么for循环岂不是永远执行下去了?还是说for循环内部的算法和这个稍有不同?

#5


引用 4 楼 litong534 的回复:
我也试过,同样很不理解,但是我想到了另一个问题。
你在for循环中用的是i++,如果按照上面的理解,i永远是0,永远到不了100的上限退出循环,那么for循环岂不是永远执行下去了?还是说for循环内部的算法和这个稍有不同?

不是的,在遇到自增自减运算符以后会开拓一个新的内存空间,来保存i之前的值,由于没有发生赋值,则新保存的i值(i的旧值)就没用了,下一步直接舍弃,然后i本身是完成了加1运算的。

#6


引用 4 楼 litong534 的回复:
我也试过,同样很不理解,但是我想到了另一个问题。
你在for循环中用的是i++,如果按照上面的理解,i永远是0,永远到不了100的上限退出循环,那么for循环岂不是永远执行下去了?还是说for循环内部的算法和这个稍有不同?


int j=0; int i = 0;
int x = j++ + j++ + ++j;
int y = i++ + i++ + i++;
System.out.println("x:"+x+"y:"+y);

这两个赋值语句,x= 0(j++)+ 1(j++)+3(++j) = 4;
y = 0(i++)+1(i++)+2(i++) = 3;
从另一个角度来看,i++操作具有一个延时效果,在本次计算的时候还是i原来的值,在下一次使用i值进行计算就是加1的结果;而++i不同,先在i原值的基础上加1,然后用更新后的i值参与计算。
上面对x赋值时,最后一个++j,上一步更新后的j为2,在此基础上+1参与计算记为3,所以最后结果为4;
对y赋值时,最后一个i++,用i的原值进行计算,之后i值更新,所以为3.