argius note

プログラミング関連

匿名クラスとラムダ式で作られるクラスファイルの違い

短いエントリーです。


ご存知の方も多いと思いますが、従来RunnableComparatorのような関数様パラメーターのメソッドローカル実装は匿名クラスで賄っていましたが、Java8からはラムダ式で書けるようになりました。


匿名クラスは、エンクロージングクラス名+$1.class(例:App$1.class)のような名前でクラスファイルが作られます。数字は連番で、2つ目は$2.classとなります。
ラムダ式は、エンクロージングクラスのクラスファイル内部に合成メソッドとして作成されます。メソッド名は、lambda$+エンクロージングメソッド名+$1(例:lambda$main$1)のような名前になります。数字が連番なのは同じです。



それでは、実際に作成されるクラスファイルはどのような違いがあるのでしょうか。
簡単なサンプルコードで試してみました。

  • 匿名クラスバージョン(App1.java)
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ForkJoinPool;

public final class App1 {

    public static void main(String[] args) {
        Callable<String> task1 = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "task1";
            }
        };
        Callable<String> task2 = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "task2";
            }
        };
        Callable<String> task3 = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "task3";
            }
        };
        ForkJoinPool.commonPool().invokeAll(Arrays.asList(task1, task2, task3));
    }

}

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ForkJoinPool;

public final class App2 {

    public static void main(String[] args) {
        Callable<String> task1 = () -> {
            return "task1";
        };
        Callable<String> task2 = () -> {
            return "task2";
        };
        Callable<String> task3 = () -> {
            return "task3";
        };
        ForkJoinPool.commonPool().invokeAll(Arrays.asList(task1, task2, task3));
    }

}

  • それぞれのファイルサイズ
App1.java
bytes file name
  647 App1$1.class
  647 App1$2.class
  647 App1$3.class
  724 App1.class
2,451 app.jar

App2.java
bytes file name
1,482 App2.class
1,229 app.jar

単純計算すると、1つの匿名クラス当たり400バイト減っています。これは、100の匿名クラスをラムダ式に置き換えたとしたら、39KB程度減る計算になります。


サイズを減らすためにラムダ式を使うなんてことはまず無いと思いますが、なんとなく得した気分になるというお話でした。

(おわり)