バイトコードの角度からi++と++iの実現を分析する

1962 ワード

最近面接の問題を見ました.
int j=0;
for(int i=0;i<100;i++)
    j = j++;
System.out.println(j);

出力結果は0で、j++に置き換えると、出力100は、なぜですか?
このような問題に対して、実は少し経験のあるプログラマーはすべて知っていて、前置++と後置++の演算の違い:
1、前置++は、自身に1を加えた値を新しい変数に与えるとともに、自身にも1を加える
2、後置++は自分の値を新しい変数に割り当ててから、自分で1を加える.
とはいえ、上の2点を証明するにはどうすればいいのでしょうか.
万物には始まりと終わりがあり、コードについては、バイトコードの観点から価値のある情報を掘り起こすことができるかどうかを見るしかない.
バイトコードを話す前に、Javaスタックを簡単に理解しておくと、JVMにはJavaスタックというデータ構造があり、スレッドが起動すると、そのスレッドのスタックとしてメモリが割り当てられ、各スタックは一連のスタックフレームから構成されています.各スタックフレームは、スレッドがメソッドを実行すると、スタックフレームがスタックにスタックされるプロセスに対応する.
各スタックフレームは、ローカル変数(パラメータ+メソッド内の変数)、オペランドスタック、およびその他のデータの3つの部分を含み、本明細書では主にローカル変数およびオペランドスタックに関する.

まず、後置++の実装を見てみましょう.
public static void main(String[] args){
    int i= 0;
    i = i++;
}

コンパイル後のバイトコードは次のとおりです.
iconst_0  //   0 push     
istore_1 //              2   
iload_1 //       2     push     
iinc 1,1  //        2    1     
istore_1 //              2   

プロセス全体は次のようになります.

変数aはiinc 1,1を実行するときに1になっていることがわかりますが、istore_1また変数aの位置を0に上書きしたので,i=i+,iは元の値となる.
また、前置++の実装を見てみましょう.

バイトコードは説明されなくなり、プロセス全体は以下のように実現されます.

後置++と異なる点は、変数がオペランドスタックに入る前にiinc命令が実行されているため、オペランドに入る値はプラス1の値であり、最後に書き込まれた値も最新値である.
オオカミの兄のブログから転載しますhttps://www.jianshu.com/p/7988e646a37e