java中++的迷惑行为

2 篇文章 0 订阅

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先自增,然后返回自增后的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值