我很难用Java包围非静态嵌套类。请考虑以下示例,其中打印“内部”,然后打印“子”。
class Outer {
class Inner {
Inner() { System.out.println("Inner"); }
}
}
public class Child extends Outer.Inner {
Child(Outer o) {
o.super();
System.out.println("Child");
}
public static void main(String args[]) {
new Child(new Outer());
}
}
我理解Inner的实例总是必须与外部实例相关联,并且它也适用于Child,因为它扩展了Inner。我的问题是o.super()
语法的含义 - 为什么它会调用Inner构造函数?
我只看到一个普通的super(args)
用于调用超类构造函数,而super.method()
用于调用重写方法的超类版本,但是从来没有形式instance.super()
。< / p>
答案 0 :(得分:11)
它被称为“合格的超类构造函数调用”。
引自here:
显式构造函数调用语句可以分为两种:
备用构造函数调用以关键字this开头(可能以显式类型参数开头)。它们用于调用同一类的备用构造函数。
超类构造函数调用以关键字super(可能以显式类型参数开头)或Primary表达式开头。它们用于调用直接超类的构造函数。超类构造函数调用可以进一步细分:
不合格的超类构造函数调用以关键字super开头(可能以显式类型参数开头)。
合格的超类构造函数调用以Primary表达式开头。它们允许子类构造函数显式指定新创建的对象关于直接超类(第8.1.3节)的直接封闭实例。当超类是内部类时,这可能是必要的。
答案 1 :(得分:10)
内部类(非静态子类)本质上是嵌套类(静态子类),其隐式链接返回其父对象。以下是您使用静态嵌套类编写的上述代码:
class Outer {
static class Inner {
final Outer outer;
Inner(Outer outer) {
this.outer = outer;
System.out.println("Inner");
}
}
}
public class Child extends Outer.Inner {
Child(Outer o) {
super(o); // o.super();
System.out.println("Child");
}
public static void main(String args[]) {
new Child(new Outer());
}
}
看看这个,你应该能够理解o.super()正在做什么。
答案 2 :(得分:6)
为什么o.super()
中的Child
最终会调用Outer.Inner
构造函数?这很简单:因为Child extends Outer.Inner
和构造函数调用总是在层次结构中链接。
以下是对您的代码段的轻微扩展,以说明:
class Outer {
Outer() {
System.out.println("Outer");
}
void outerMethod() { }
class Inner {
Inner() {
System.out.println("OuterInner");
outerMethod();
}
String wealth;
}
}
class OuterChild extends Outer {
OuterChild() {
System.out.println("OuterChild");
}
}
public class OuterInnerChild extends Outer.Inner {
OuterInnerChild(Outer o) {
o.super();
System.out.println("OuterInnerChild");
this.wealth = "ONE MILLION DOLLAR!!!";
}
public static void main(String args[]) {
System.out.println(new OuterInnerChild(new Outer()).wealth);
new OuterChild();
}
}
打印:
Outer
OuterInner
OuterInnerChild
ONE MILLION DOLLAR!!!
Outer
OuterChild
一些重要的观察结果:
OuterInnerChild extends Outer.Inner
,它继承wealth
,就像普通的子类语义一样
OuterInnerChild
的构造函数链接到Outer.Inner
的构造函数OuterChild extends Outer
,它的构造函数链,即使没有显式调用
但是为什么编译器要求
OuterInnerChild
构造函数采用Outer o
,并调用o.super()
?
现在这是特定于内部类语义的:它是为了确保OuterInnerChild
的所有实例都有Outer
的{{1}}实例,Outer.Inner
的超类。 。否则,OuterInnerChild
的构造函数将没有Outer.Inner
的封闭实例来调用Outer
。
答案 3 :(得分:2)
从概念上讲,非静态内部类“属于”特定对象。它有点像每个人都有自己的类版本,就像非静态字段或方法属于特定对象。
这就是为什么我们有像instance.new Inner()
和instance.super()
这样有趣的语法 - 对于问题的回答“而 <{em> Inner
?”isn'的上下文t立即显而易见。 (在外部类的非静态方法中,您可以说new Inner()
,并且像往常一样this.new Inner()
的缩写。)
答案 4 :(得分:0)
始终不要忘记基本原则,在调用子类构造函数的过程中,无论内部/外部类如何,首先实例化父类。在您的场景中,当您扩展内部类时,您的内部类是父类的成员,需要实例化,然后调用实际的内部类构造函数。