Javaクラスメソッドでcacheクラス変数を使用する理由

2158 ワード

たとえば、次のjavaコードです.
private void performTraversals() {
    // cache mView since it is used so much below...
    final View host = mView;

    ......
}

どうしてそう書くのですか.
次のテストプログラムのbytecodeで説明します(以下のbytecodeはJVMベースであり、artベースではありません):
public class TestLocal {
    private int i = 1;

    public void foo() {
        long before = System.currentTimeMillis();
        for (int j = 0; j < 10000; j++) {
            System.out.print(i);
        }

        System.out.println();
        System.out.println("TestLocal result: " + (System.currentTimeMillis() - before));
    }

    public static void main(String[] args) {
        new TestLocal().foo();
        new TestLocal2().foo();
    }
}


class TestLocal2 {
    private int i = 1;

    public void foo() {
        int k = i;
        long before = System.currentTimeMillis();
        for (int j = 0; j < 10000; j++) {
            System.out.print(k);
        }

        System.out.println();
        System.out.println("TestLocal2 result: " + (System.currentTimeMillis() - before));
    }
}
TestLocalfooメソッドは、クラス変数を直接読み出し、対応するバイトコードは
        13: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        16: aload_0
        17: getfield      #2                  // Field i:I
        20: invokevirtual #5                  // Method java/io/PrintStream.print:(I)V

毎回このpushをoperand stackに入れ、対応するfieldをスタックに探します.TestLocal2fooメソッドは、クラス変数の値を現在のFrameのlocal variableに格納します.そして呼び出すたびにlocal variableから取り出すだけです.
         0: aload_0
         1: getfield      #2                  // Field i:I
         4: istore_1
         .......
        20: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        23: iload_1
        24: invokevirtual #5                  // Method java/io/PrintStream.print:(I)V

実行時間の比較:
TestLocal result: 145 ms
TestLocal2 result: 128 ms

したがって、クラス変数をメソッドのlocal variableにキャッシュすると、特にクラス変数が頻繁にアクセスされる場合、実行速度が向上します.