Java 中的 i = i++ 问题

Posted 善良超锅锅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 中的 i = i++ 问题相关的知识,希望对你有一定的参考价值。

Java 中的 i = i++ 问题

今天实验室几个 Java 技术栈的小伙伴在讨论问题,感觉他们在讨论一个很简单但又很有意思的问题。想到我最近也要用 Java,于是过去看了一下。没想到他们居然像 C/C++ 程序员一样在讨论 i++ 的问题。看来 Java 程序员也不能免俗。而且《Java 程序员面试笔试宝典》也提到了这个问题。网上也可以搜到好多结果。看来这个问题很重要,虽然是个无聊的问题,但说不定以后找工作会遇到,还是研究一下。

问题

问题如下,假设有一段代码是这样的

int i = 0;
i = i++;
System.out.println(i);  // 0

问最后的输出结果是什么。我这两天才开始看 Java,第一眼就认为肯定是输出 1 ,但如果结果真的这么直观就不会出成笔试题了。实际运行一下,结果居然是输出 0。

如果把 i = i++ 换成 i = ++i 或者干脆换成 i++。输出结果就是 1 了。为了完整性,把替换后的代码也贴一下。

int i = 0;
i++;
System.out.println(i);  // 1
int i = 0;
i = ++i;
System.out.println(i);  // 1

解释

这个问题其实想明白了就很简单,只需要理解两个关键的地方:1. 表达式的返回值。 2. 临时变量。不信我们先来分析大家都知道的 i++++i 的区别。假设有下面一段 Java 代码:

// e.g.1
int i = 0;
int j = 0;
int a = ++i;  // a=1, i=1
int b = j++;  // b=0, j=1

问最后 i j a b 的值各是什么。相信很多人都能得到正确答案。所以我把答案直接注释在代码中了。很多人也能解释个所以然来。但我们还是来分析一下:

a 的结果是表达式 ++i 的值,而 b 的结果是表达式 j++ 的值。大多数人都知道 ++i 返回的是 i 自增以后的值,而 j++ 返回的是 j 自增以前的值。a b 值不一样,也就是表达式 ++i 和表达式 j++ 的返回值不一样。

上面说这么啰嗦就是为了让大家注意到表达式的返回值的概念。表达式都是有返回值的,不然就不能放在赋值操作符右边了。而且无论多么复杂的表达式都是在表达式计算完后才返回一个值(注意是计算完后)。表达式 ++i 的返回值就是 i 自增后的值,而表达式 j++ 的返回值是 j 自增前的值。

OK,我们终于引入了表达式的返回值这个概念。再思考一下, 表达式 ++i 直接在 i 自增完后返回 i 的值就行。那 j++ 要返回 j 自增前的值,怎么做到?难道先返回 j 的值,然后再让 j 自增吗?不行,因为表达式计算结束后才能返回一个值。编译器普遍的做法是创建一个临时变量来保存 j 自增前的值,在 j 自增完后再返回这个临时变量的值。所以 b = j++ 底层发生的步骤如下:

step1: temp = j; // 创建一个临时变量 temp 保存 j 的值,这个 temp 也是整个表达式的返回值
step2: 对 j 进行自增操作
step3: 将表达式的返回值 temp 赋值给 b

然后临时变量 temp 的使命就完成了。

注:可能有部分人误以为:表达式 j++ 是先返回 j 的值,然后再对 j 进行自增操作。这种理解是错误的。如果表达式都返回了,还计算个球。表达式只有在计算完后才会进行返回。无论多么复杂的表达式,返回值都在最后一步。

OK,到了这里,原始问题就很清晰了。

int i = 0;
i = i++;
System.out.println(i);  // 0

i = i++ 对应的步骤如下:

step1: 创建一个临时变量 temp 保存 i 的值 // temp=i=0,temp 也是整个表达式的返回值
step2: 对 i 进行自增操作  // i 的值变成了 1
step3: 返回表达式的值,也就是将 temp 赋值 给 i  // i 的值变成了 temp 的值,所以 i 又变成了 0

后记

后来发现,不能理解这个问题的人其实也没真正理解 ++ii++ 的区别,没有明确意识到表达式表达式的返回值的概念。

Java 这种面向工业级生产语言,照理说应该比较中庸保守,为什么不把 ++ii++ 变成一样呢。去掉这个特性多好。和 C/C++ 彻底划清界限才是 Java 的正道。

以上是关于Java 中的 i = i++ 问题的主要内容,如果未能解决你的问题,请参考以下文章

Java中的原子操作类

Java中的I/O流

java 中的<<是啥意思?byte a= 64 ,i=a<<2,为啥i 就等于256?

第七章 Java中的13个原子操作类

Java 中的 i = i++ 问题

Java 中的 i = i++ 问题