2011年3月14日月曜日

[Java]匿名クラスにfinal変数が展開されると

ローカル変数にfinalをつけると、内部で生成している匿名クラスに展開されます。
で、どのように展開されるかというと、匿名クラスのコンストラクターの引数になり、自動生成される同名のメンバ変数に展開されるようです。
とは書いたものの、実際にどうなるかを、classファイルからリバースしてみました。

■変換前のソース
final int hoge1 = 1;
final int hoge2 = 2;
final URL url =new URL("http://localhost/");

btn2.addActionListener(new ActionListener() {
    int hogehoge = 0;
    public void actionPerformed(ActionEvent evt) {
        this.hogehoge = hoge1 + hoge2;
        System.out.print("hogehoge=" + hogehoge);
        System.out.print("hoge1=" + hoge1);

        System.out.print("url=" + url);

        exec();
    }

});


■変換後のソース(一部修正)
/*  51*/        int hoge1 = 1;
/*  52*/        int hoge2 = 2;
/*  53*/        final URL url = new URL("http://localhost/");

/*  55*/        btn2.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt)
                    {
/*  58*/                hogehoge = 3;
/*  59*/                System.out.print((new StringBuilder("hogehoge=")).append(hogehoge).toString());
/*  60*/                System.out.print("hoge1=1");

/*  62*/                System.out.print((new StringBuilder("url=")).append(url).toString());

/*  64*/                exec();
                    }
                    int hogehoge;
                    final RefrectionPanel this$0;
                    private final URL val$url;
                    
                    {
/* <-MISALIGNED-> */ /*   1*/                this$0 = RefrectionPanel.this;
/* <-MISALIGNED-> */ /*   1*/                url = url1;
/* <-MISALIGNED-> */ /*  55*/                super();
/* <-MISALIGNED-> */ /*  56*/                hogehoge = 0;
                    }
        }


・・・なんとなく雰囲気はわかるんですが、そのままだとコンパイルエラーです。しかし、コンストラクタでコピー(しようとしている)感じはわかりますね。面白いのは、int型(おそらくプリミティブ)については、値に展開されるところでしょうか。興味深いです。
あ、コレでちょっとしたリバースエンジニアリング対策にもなりますね。

0 件のコメント: