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

NO IMAGE
1 Star2 Stars3 Stars4 Stars5 Stars 給文章打分!
Loading...

只要是會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 //方法返回

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

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

最後,感謝基友默默與我一起研究這個問題,他的部落格地址:
http://zhaohe162.blog.163.com/

相關文章

程式語言 最新文章