inti =0;
i = i++;
|
結果仍是0
爲何?
程序的執行順序是這樣的:由於++在後面,因此先使用i,「使用」的含義就是i++這個表達式的值是0,可是並無作賦值操做,它在整個語句的最後才作賦值,也就是說在作了++操做後再賦值的,因此最終結果仍是0 java
讓咱們看的更清晰點: c++
inti =0;//這個沒什麼說的
i = i++;//等效於下面的語句:
|
inttemp = i;//這個temp就是i++這個表達式的值
i++;//i自增
i = temp;//最終,將表達式的值賦值給i
|
這是java裏的實現,固然在其餘的語言如c或是c++中可能並非這麼處理的,每種語言都有各自的理由去作相應的處理。 學習
這警示咱們:不要在單個的表達式中對相同的變量賦值超過一次 spa
讓咱們從字節碼層次看一看,源碼以下: 索引
publicclassTest {
publicstaticvoidmain(String... args) {
inti =0;
i = i++;
System.out.println(i);
}
}
|
使用javac編譯後再使用javap -c Test反編譯這個類查看它的字節碼,以下(只摘取main方法): ci
public static void main(java.lang.String[]); get
Code: 源碼
0: iconst_0 虛擬機
1: istore_1 io
2: iload_1
3: iinc 1, 1
6: istore_1
7: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
10: iload_1
11: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
14: return
這裏,我從第0行開始分析(分析中【】表示棧,棧的底端在左邊,頂端在右邊):
0:將常數0壓入棧,棧內容:【0】
1:將棧頂的元素彈出,也就是0,保存到局部變量區索引爲爲1(也就是變量i)的地方。棧內容:【】
2:將局部變量區索引爲1(也就是變量i)的值壓入棧,棧內容:【0】
3:將局部變量區索引爲1(也就是常量i)的值加一,此時局部變量區索引爲1的值(也就是i的值)是1。棧內容:【0】
6:將棧頂元素彈出,保存到局部變量區索引爲1(也就是i)的地方,此時i又變成了0。棧內容:【】
7:獲取常量池中索引爲2所表示的類變量,也就是System.out。棧元素:【】
10:將局部變量區索引爲1的值(也就是i)壓入棧。棧元素:【0】
11:調用常量池索引爲3的方法,也就是System.out.println
14:返回main方法
看了你的文章,我我的理解是,例如:int i = a + b;是將a,b壓入操做數棧,經過+出棧,付給局部變量區的i。而i++並非在操做數棧執行的自加,而是在局部變量區對嗎。若是是的,請問還有那些操做不是在操做數棧
iinc指令是直接操做局部變量區的.其它不與操做數棧打交道的指令卻是沒有統計過,能夠參見《Java虛擬機規範 Java SE 7 版》的第六章,裏面詳細的列出了每一個指令的用途以及操做前和操做後棧的變化。
return就相似於java語言中的return,咱們在寫void方法的時候,也能夠用return提早結束方法。若是返回值是int,那麼用的指令不是return,而是ireturn;對於引用是areturn;對於long,float,double等都有本身的return指令。單單一個return就表示返回值是void。