java面试题遇到一些有关++奇葩题,奇葩之题必有奇葩之处,很有迷惑性。关于i++和++i我看到一篇很不错的帖子,写的非常不错。有兴趣可以去看看。
烟雾弹案例1
i++和++i的区别是什么?
很多人肯定听过这么一句话:
++ i 是先加后赋值;i ++ 是先赋值后加。
如果你也是这么认为的话,那来先做一道题:
public void test(){
int i=0;
int a=0;
a=i++;
System.out.println("a的值是"+a);
System.out.println("i的值是"+i);
}
输出结果:
a的值是0
i的值是1
这道题肯定都做对了。
来继续做下一题
案例2:
public void test(){
int i=0;
i=i++;
System.out.println("i的值是"+i);
}
运行结果:
i的值是0
有些不可思议,来看看
javap反编译后的字节码文件:
0 iconst_0 //加载常量0到操作数栈
1 istore_1 //将栈顶0弹出,存进局部变量表索引为1
2 iload_1 //加载局部变量表索引为1的变量
3 iinc 1 by 1 //局部变量表中i+1,操作数栈中无变化
6 istore_1 //将栈顶0弹出,存进局部变量表索引为1
7 getstatic #6 <java/lang/System.out>
10 iload_1
11 invokevirtual #100 <java/io/PrintStream.println>
14 return
看不懂也没关系,就看这两行
3 iinc 1 by 1
6 istore_1
是先自增再赋值,可以证明++ i 是先加后赋值;i ++ 是先赋值后加这个结论在java中是错的。
小总结:
在java中,一般会先计算优先级高的,再计算优先级低的。=的优先级是最低的,++优先级是很高的仅次于(),怎么可能会先赋值再加?
那如何解释案例1和2?请看案例3
案例3
public static void main(String[] args) {
int i=0;
System.out.println(i++);
}
字节码:
0 iconst_0
1 istore_1
2 getstatic #2 <java/lang/System.out>
5 iload_1
6 iinc 1 by 1
9 invokevirtual #3 <java/io/PrintStream.println>
12 return
请问打印结果是多少?i是多少?
毫无疑问,打印结果是0,i是1
三条解释帮助你理解:
首先,
解释1:++是单目运算符,既然i++可以println打印出来,说明i++是有返回值的,从案例3可以看出i++的返回值是i,i先自增,然后返回自增前的值。
解释2:可以看成有一个临时变量temp接收了i,然后i+1,再返回temp这个临时变量
**解释3:**从字节码的角度去分析,先把i的值0压入操作数栈,然后局部变量表中i从0自增到1,再把栈顶的值0弹出,做一个println输出
int temp = i;
i = i + 1;
return temp;
案例4
最后一道题,看看打印结果是多少?如果正确说明已经理解了++的迷惑行为。
public class IncTest {
public int i=0;
public int getI(){
return i++;
}
public static void main(String[] args) {
IncTest test = new IncTest();
System.out.println(test.getI());
System.out.println(test.i);
}
}
输出结果是:
0
1
getI()返回的结果确实是0,但是i已经是1了。
过程是i先从0自增为1,然后返回自增前的值0
无论是i++,还是++i,都会先自增1,然后再返回。
i++,i先自增,然后返回自增前的值
++i,i先自增,然后返回自增后的值