Anonymous classのコンパイル
外側のローカル変数にどうやってアクセスしているのか
コンストラクタ経由で、変数を渡してアクセスしている。(なるほどfinalでなくてはいけないわけだ)
public class Foo { public void Test() { final String x = "Hello World"; Bar y = new Bar() { public void func() { System.out.println(y); }; y.func(); return; } }
は、
public class Foo$1 implements Bar { private final String x; public Foo$1(String x1) { x = x1; } public void func() { System.out.println(x); } } public class Foo { public void Test() { final String x = "Hello World"; Bar y = new Foo$1(x); y.func(); return; } }
外側のクラスのメンバにどうやってアクセスしているのか
コンストラクタで外側のクラスのインスタンスを渡し、フィールドに格納しておく。また、外側のクラスの変数に対応するStaticなアクセッサを適当に定義しておく。変数へのアクセスは、コンストラクタに渡されたインスタンスと、スタティックなアクセッサを利用して行う。
class Foo { private int value; public Test() { Bar x = new Bar() { public void func() { value = 2; } }; x.func(); } }
は、
class Foo$1 implements Bar { private Foo this1; public Foo$1(Foo this0) { this1 = this0; } public void func() { Foo.setvalue(this1, 2); } } class Foo { private int value; public void Test() { Bar x = new Foo$1(this); x.func(); } public static void setvalue(Foo inst, int i) { inst.value = i; } public static int getvalue(Foo inst) { return inst.value; } }
みたいな感じ。
賢いなあ。
*1:実際には、Stringはimmutableなので、なんか最適化されてたけど(わかりにくい)