シリーズ第3弾!
君は合成メソッドを知っているか!(Java) - Fight the Future じゅくのblog
君は合成フィールドを知っているか!(Java) - Fight the Future じゅくのblog
合成コンストラクタ。つまりコンパイラが自動的に作成するコンストラクタ。
やはりインナークラス関連で作成される。
アウタークラスのコンストラクタがprivateとする。
でもインナークラスであれば、そのprivateなアウタークラスのコンストラクタを呼び出すことができる。
こういう場合、合成コンストラクタが作成される。
このこともSunのサイトに記述があった。
Retrieving and Parsing Constructor Modifiers (The Java™ Tutorials >
The Reflection API > Members)
少しコードを簡略化して動作させてみた。
import java.lang.reflect.Constructor; public class SyntheticConstructor { private SyntheticConstructor() {} class Inner { Inner() { // Compiler will generate a synthetic constructor since // SyntheticConstructor() is private. new SyntheticConstructor(); } } public static void main(String... args) { try { Class<?> c = Class.forName("SyntheticConstructor"); Constructor[] allConstructors = c.getDeclaredConstructors(); for (Constructor ctor : allConstructors) { System.out.format("%s%n", ctor.toGenericString()); System.out.format(" [ synthetic=%-5b ]%n", ctor.isSynthetic()); } } catch (ClassNotFoundException x) { x.printStackTrace(); } } }
アウタークラスがSyntheticConstructorクラス、インナークラスがInnerクラス。
Innerクラスのコンストラクタでアウタークラスのprivateコンストラクタを呼び出している。
このコードを実行するとこうなる。
private SyntheticConstructor() [ synthetic=false ] SyntheticConstructor(SyntheticConstructor) [ synthetic=true ]
SyntheticConstructorクラスに、もともとあるprivateなコンストラクタの他に、修飾子なしの(package privateの)コンストラクタが作成されている。
これが合成コンストラクタ。
こう記述がある。
Since the inner class's constructor references the private constructor of the enclosing class, the compiler must generate a package-private constructor. The parameter type SyntheticConstructor$1 is arbitrary and dependent on the compiler implementation. Code which depends on the presence of any synthetic or non-public class members may not be portable.
Retrieving and Parsing Constructor Modifiers (The Java™ Tutorials > The Reflection API > Members)
エンクロージングクラスのprivateコンストラクタを参照するインナークラスのコンストラクタがあるので、コンパイラはpackage-privateなコンストラクタを生成する。
引数の型SyntheticConstructor$1はコンパイラの実装に依存する。
こういうのをコードで使うとポータブルじゃないよ。
ところで、Sunのサイトの実行結果は「SyntheticConstructor(SyntheticConstructor$1)」とあるけど、
僕の実行結果は「SyntheticConstructor(SyntheticConstructor)」だった。
Macだからコンパイラの実装も異なってるからかな。
よかったらいろんなOSの人、実行してみてもらえません??
コピペで動きます。
結果をコメントでもらえるとうれしいです。