君は合成メソッドを知っているか!(Java)に続いて第2弾。
前回はMethodクラスのisSynthetic()を調べたわけだけど、
そもそもisSynthetic()はMethodクラスのインタフェースであるMemberに定義されている。
Memberインタフェースを実装するクラスとして、Method、Field、Constroctorがある。
今回はフィールドについて調べてみる。
FieldがisSynthetic()である、つまり合成フィールドってなんだ?ってこと。
synthetic(合成)はコンパイラが自動的に作成するという意味。
ならば「合成フィールドとはコンパイラが作成するフィールド」ということになる。
ではどんなときにコンパイラはフィールドを作成するのか?
検索するとSunのサイトに解説があった。
http://java.sun.com/docs/books/tutorial/reflect/member/fieldModifiers.html
インナークラスを作成したときに、そのインナークラスに合成フィールドが作られることがあるらしい。
SunのサンプルはなんかEnumのやつも混じってるので、すっきりさせてみた。
import static java.lang.System.out; import java.lang.reflect.Field; public class Test { class Inner { String aaa; } public static void main(String[] args) throws Exception { try { Class<?> c = Class.forName("Test$Inner"); Field[] flds = c.getDeclaredFields(); for (Field f : flds) { out.format("%-8s [ synthetic=%-5b ]%n", f.getName(), f .isSynthetic()); } } catch (ClassNotFoundException x) { x.printStackTrace(); } } }
TestクラスのインナークラスとしてInnerを定義する。
Innerには比較のためにフィールドを1つ定義する(aaa)。
main()メソッドではInnerクラスのClassを取得して、すべてのフィールドを出力する。
本来、Innerクラスにはフィールドとしてaaaしかないはず。
しかし、実行するとこうなる。
aaa [ synthetic=false ] this$0 [ synthetic=true ]
定義した覚えがない「this$0」というフィールドを出力している。
そして、syntheticがtrueになっている。
つまり、これが合成フィールドのようだ。
こう記述があった。
the compiler will generate some synthetic fields which are needed during runtime. To test whether a field is synthetic, the example invokes Field.isSynthetic(). The set of synthetic fields is compiler-dependent; however commonly used fields include this$0 for inner classes (i.e. nested classes that are not static member classes) to reference the outermost enclosing class
Retrieving and Parsing Field Modifiers (The Java™ Tutorials > The Reflection API > Members)
この場合、インナークラスからもっとも外にあるエンクロージングクラスを参照できるように、合成フィールドが作成されるようだ。