概述
- 自增运算符:++,自减运算符:- -。
- 自增自减运算符是只对一个变量运算的运算符,故为一目运算符
- 值得注意的是运算符在操作数前和在操作数后的效果有时会截然不同
前缀自增自减法与后缀自增自减法
格式:++操作数或- -操作数
相当于:操作数=操作数+1或操作数=操作数-1
前缀自增自减法中操作数是先进行自增或自减操作,再被使用。
格式:操作数++或操作数- -
相当于:操作数=操作数+1或操作数=操作数-1
前缀自增自减法中操作数是先被使用,再进行自增或自减操作
先用一段简单的代码展示两者的区别:
int n = 1;
int m = 1;
int a = n++;
int b = ++m;
System.out.println(a);
System.out.println(n);
System.out.println(b);
System.out.println(m);
运行结果:
分析:
变量a的值是1,这是因为变量n的自增操作是后缀自增自减法,先将变量n的初值1赋值给变量a,然后再进行自增操作,n的值变为2。相当于:a=n;n=n+1;。
变量b的值是2,这是因为变量m的自增操作是前缀自增自减法,先进行自增操作,m的值变为2,然后再将变量m的值2赋值给变量b,b的值也变为2。相当于:m=m+1;b=m;。
int i = 1;
i = i++;
System.out.println(i);
这里的输出结果不是2,而是1。可能有人会说,哎呀不对啊,按照前面的讲述,这里的i=i++应该相当于i=i;i=i+1;,这样这个结果应该是2才对啊。那么这里就涉及到了JVM内存模型,要从内存出发来理解操作数在内存中的储存过程。
如果觉得理解这个太过麻烦,也可以只记住i=i+1这种特殊形式和结果,如果想要了解原理,请耐心看完。
每一个操作数在JVM中都有一个操作数栈(栈执行的是先进后出,后进先出的原则),JVM对操作数的存储过程就基于对操作数栈完成的。
这一过程的执行代码大致如下(下面的操作数栈都是i的操作数栈):
0: iconst_0 (将int类型的值1入栈,对应的为第一条语句int i = 1;)
1: istore_1 (将栈内值1出栈,栈外i的值为1)
2: iload_1 (将栈外i的值1入栈,对应的为第二条语句,i=i++中i++的先用,即为i=i)
3: iinc 1, 1 (在这里对栈外的操作数执行++操作,栈外的值为2,而栈内的值仍为1)
6: istore_1 (将栈外i的值1出栈,对应的为第二条语句,i=i++中i++的后执行操作,即为i=i+1中的赋值,前一条操作为i+1,但这里的赋值是将操作数栈内的1赋值给了i,i原本的值2就被覆盖掉了)
7: iload_1 (将栈外i的值1入栈,此时i的值是1)
从这个操作过程中我们就能看出为什么i的值最终为1了,而i=++i却不会有这种情况发生。按照++i与i++的执行顺序可以可出类似的执行代码:
0: iconst_0 (将int类型的值1入栈,对应的为第一条语句int i = 1;)
1: istore_1 (将栈内值1出栈,栈外i的值为1)
2: iinc 1, 1 (在这里对栈外的操作数执行++操作,栈外的值为2,而栈内的值仍为1)
3: iload_1 (将栈外i的值2入栈)
6: istore_1 (将栈外i的值2出栈,此时i的值为2)
7: iload_1 (将栈外i的值2入栈,此时i的值是2)
由此我们也能看出++i与i++的区别,++i是先入栈再++,而++i是先++再入栈。