また合成関係で疑問が出た。
そもそも合成コンストラクタについては下記参照で。
君は合成コンストラクタを知っているか!(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にしたりして、可視性を上げれば警告は消えるよ。