Java:私有内部类合成构造函数
这个问题在这里已经有了答案:
如果你写这样的代码,
public class Outer {
private class Inner {}
}
你会注意到只有一个构造函数是private Outer$Inner(Outer)
这个构造函数是JLS第8.8.9节要求的,它说如果没有定义构造函数,就必须生成一个默认的构造函数,在这种情况下,默认的构造函数必须是私有的,
在类类型中,如果该类声明为public,则默认构造函数隐式赋予访问修饰符public(§6.6); 如果该类声明为protected,则默认的构造方法隐式赋予访问修饰符protected(§6.6); 如果这个类声明为private,那么默认的构造函数隐式给出访问修饰符private(§6.6); 否则,默认的构造函数具有默认的访问权限,不存在访问修饰符。
然而,当你用类似代码实例化外部内部的一个实例时,
public class Outer {
private class Inner {}
public String foo() {
return new Inner().toString();
}
}
编译器必须生成一个Outer可以合法调用的构造函数(因为它是私有的,所以不能合法地调用私有的默认构造函数)。 所以编译器必须生成一个新的合成构造函数。 根据JLS第13.1节的规定,新的构造函数必须是合成的
编译器引入的任何源代码中没有相应构造的构造必须标记为合成构造,除了默认构造函数和类初始化方法。
这第二个构造函数在源代码中没有相应的构造,所以这个新的构造函数必须是合成的。 由于JLS需要私有默认构造函数,所以仍然必须生成第一个私有构造函数。
这不是一个答案,我认为这已经被sbridges所覆盖。 它只是一个可以产生你描述的行为的工作示例:
public class Outer {
private class Inner {
}
public static void main(String[] args) {
printConstructors();
//only one constructor is printed but two would appear if you
//uncommented the line below
//new Outer().new Inner();
}
private static void printConstructors() {
Constructor[] constructors = Outer.Inner.class.getDeclaredConstructors();
for (Constructor c : constructors) {
System.out.println(c.toGenericString());
}
}
}
最可能的答案是尊重你在源代码中声明的内容。 这样做仍然允许在声明时通过反射使用私有构造函数。
这也避免了检查私有构造函数是否在Inner
类中实际调用。
上一篇: Java: private inner class synthesized constructors
下一篇: Difference between <? super T> and <? extends T> in Java