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
后记
后来发现,不能理解这个问题的人其实也没真正理解 ++i
和 i++
的区别,没有明确意识到表达式和表达式的返回值的概念。
Java 这种面向工业级生产语言,照理说应该比较中庸保守,为什么不把 ++i
和 i++
变成一样呢。去掉这个特性多好。和 C/C++ 彻底划清界限才是 Java 的正道。
以上是关于Java 中的 i = i++ 问题的主要内容,如果未能解决你的问题,请参考以下文章