java.lang.inc,關於java的 和–操作符,你真的搞明白了嗎?

博客详细解释了Java中i++和++i操作符的工作原理,并通过位元组码分析了它们的区别。文章以一个简单的循环示例说明了为何在某些情况下,变量值可能不会如预期般改变。同时,文章还探讨了iinc指令在区域变量表中的操作方式,强调了其对变量值的影响。最后,通过对比i和i的执行过程,加深了读者对这两个操作符的理解。
摘要由CSDN通过智能技术生成

只要是會java的都知道 和—操作符的用法,如

int i = 1;

int j = i ;

int k = i;

結果i為3,j為1,k為3。

那如下程式碼:

int j = 0;

for (int i = 0; i < 100; i ) {

j = j ;

}

System.out.println(j);

輸出結果又是多少呢?100?0?

正確答案是0。為什麼呢?

要想搞明白這個問題,那來看看這段程式碼生成的位元組碼:

0: iconst_0

1: istore_1

2: iconst_0

3: istore_2

4: goto 15

7: iload_1

8: iinc 1, 1

11: istore_1

12: iinc 2, 1

15: iload_2

16: bipush 100

18: if_icmplt 7

21: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;

24: iload_1

25: invokevirtual #22; //Method java/io/PrintStream.println:(I)V

28: return

j = j ;的位元組碼為:7: iload_1

8: iinc 1, 1

11: istore_1

iload_1 意思是把區域性變數表中位置1的變數取出來放到運算元棧中;

iinc    1, 1 這是執行j 操作,把區域性變數表中位置1的變數加1;

istore_1 這是把運算元棧頂的值彈出放到區域性變數表位置1的變數中。

問題就在innc這個指令,指令格式為:

innc vindex const

這個指令只能操作int型別的變數,有兩個運算元,第一個運算元vindex指示區域性變數在區域性表中的位置索引,第二個運算元const表示要相加的整型常量。如

innc 2 100

表示把區域性變數表中位置2的變數加上100。

具體的過程是,把區域性變數表中位置2的變數取出來,加上100後,然後再放回到區域性變數表中。

而const這個常量值的範圍是-128~127,如果超出這個範圍,使用指令iinc_w。如:

int x = 1;

x = x -128;

x = x -129;

x = x 127;

x = x 128;

生成位元組碼如下:

0: iconst_1

1: istore_1

2: iinc 1, -128 //x = x -128;

5: iinc_w 1, -129 //x = x -129;

11: iinc 1, 127 //x = x 127;

14: iinc_w 1, 128 //x = x 128;

20: return

上面把innc指令的基本意思說清楚了,現在是最重要的一點:

innc指令操作的是區域性變數表中的變數,而不是當前運算元棧棧頂的資料(iinc指令實現有沒有用到運算元棧已經不重要了)。

上面j = j ;的位元組碼

7: iload_1

8: iinc 1, 1

11: istore_1

iload_1 先把j的值取出來放到棧頂,此時值為0,執行iinc    1, 1這個指令時,是操作的區域性變數表中變數(值為0),把它加1,此時值為1,istore_1指令把當前運算元棧頂的值(還是0),又放回區域性變數表位置1的變數中,那區域性變數表位置1的變數的值又從1變為0了。

所以,不管怎麼迴圈,j的值永遠是0。

下面說說i 和 i的問題:

都知道i 是先使用i的值,再把i的值加1;而 i是先把i的值加1,再使用i的值。

但是實際上是怎麼回事呢?其實i 和 i都是使用iinc    vindex, 1指令,區別在於,i 是先把區域性變數取出來放到運算元棧頂,再把區域性變數表中的變數值加1,而 i是先把區域性變數表中的變數值加1,再把區域性變數取出來放到運算元棧頂。如下程式碼:

int j = 0;

int x = j ;

x = j;

位元組碼如下:

0: iconst_0 //把常量0放到運算元棧頂

1: istore_1 //int j = 0;

2: iload_1 //先取出j的值0

3: iinc 1, 1 //j ,把區域性變數表中j的值加1,j=1,此時運算元棧頂的值還是0

6: istore_2 //把運算元棧頂的值0放加區域性變數表中,此時x=0

7: iinc 1, 1 // j,先把區域性變數表中j的值加1,此時j=2

10: iload_1 //取出j的值2

11: istore_2 //x=2

12: return //方法返回

以上說的都是 操作符,–的操作也是一樣的,就不再多說。

到現在終於把這個簡單的 和–徹底的搞明白了-:)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值