また合成関係で疑問が出た。
そもそも合成コンストラクタについては下記参照で。
君は合成コンストラクタを知っているか!(Java) - Fight the Future じゅくのblog
staticネストクラスにprivate修飾子をつける。
package sample; import java.lang.reflect.Constructor; public class SyntheticSample { private InnerClass innerClass = new InnerClass(); private static class InnerClass {} public static void main(String[] args) throws Exception { Constructor<?>[] constructors = InnerClass.class.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { System.out.format("%s%n", constructor.toGenericString()); System.out.format(" [ synthetic=%-5b ]%n", constructor.isSynthetic()); } } }
すると、こんな警告が出る。
Access to enclosing constructor SyntheticSample.InnerClass() is emulated by a synthetic accessor method.Incresing its visibility will improve your performance
InnerClassのコンストラクタ呼び出しは、合成アクセッサメソッドでエミュレートされている。可視性をあげるとパフォーマンスが上がるよ、と。
mainメソッドを実行すると、出力はこうなる。
private sample.SyntheticSample$InnerClass() [ synthetic=false ] sample.SyntheticSample$InnerClass(sample.SyntheticSample$InnerClass) [ synthetic=true ]
InnerClassのコンストラクタはデフォルトコンストラクタだけでなく、合成でもう1つ作られる。
InnerClassがprivateなクラスであるために、デフォルトコンストラクタもprivateとなる。
それではアウタークラスであるSyntheticSampleからアクセスできないために、コンパイラが合成コンストラクタを作るわけだ。
javapコマンドを使ってもう少し調べてみる。
#javap -c SyntheticSample$InnerClass Compiled from "SyntheticSample.java" class sample.SyntheticSample$InnerClass extends java.lang.Object{ sample.SyntheticSample$InnerClass(sample.SyntheticSample$InnerClass); Code: 0: aload_0 1: invokespecial #15; //Method "<init>":()V 4: return }
先ほどのとおり、「"
アウタークラスであるSyntheticSampleもjavapする。
#javap -c SyntheticSample Compiled from "SyntheticSample.java" public class sample.SyntheticSample extends java.lang.Object{ public sample.SyntheticSample(); Code: 0: aload_0 1: invokespecial #10; //Method java/lang/Object."<init>":()V 4: aload_0 5: new #12; //class SyntheticSample$InnerClass 8: dup 9: aconst_null 10: invokespecial #14; //Method sample/SyntheticSample$InnerClass."<init>":(Lsample/SyntheticSample$InnerClass;)V 13: putfield #17; //Field innerClass:Lsample/SyntheticSample$InnerClass; 16: return }
「//Method sample/SyntheticSample$InnerClass."
警告の解決策
staticネストクラスの修飾子をpackage privateにしたりして、可視性を上げれば警告は消えるよ。