我有三个班级
class WithInner {
class Inner {}
}
public class InheritInner extends WithInner.Inner
{ //constructor
InheritInner(WithInner wi) {
wi.super();
}
}
这个例子取自Eckel的Thinking in Java。我无法理解为什么我们不能调用wi = new WithInner();
而不是.super()?在调用wi.super()
时我们调用了Object的默认构造函数,不是吗?
答案 0 :(得分:8)
内部类维护对外部实例的引用(例外是static
内部类)。在这种情况下,WithInner.Inner
实例具有对包含WithInner
实例的引用。在实例化内部类时创建此关联。
如果没有对外部类的引用,则无法创建内部类的实例。扩展这样的内部类的类也具有这样的引用,并且需要委托给内部类构造函数以建立关联。执行此操作的语法如示例所示:
wi.super();
这里,super()
本质上是指超类构造函数 - 即WithInner.Inner
构造函数。构造函数没有正式获取参数,但它仍然需要对外部实例(类型WithInner
)的引用。整个行本质上意味着"调用超类构造函数,并与wi
实例关联#34;。
与具有显式关联的内部类的实例化语法进行比较:
wi.new WithInner.Inner()
是的,这也是有效的语法。但是,它在野外并不常见(因为内部类实例通常只是从外部类中创建,并且在这种情况下,关联是隐含的 - 在这种情况下,对此没有必要语法,它明确提供关联。)
具体参考您的问题:
我无法理解为什么我们无法调用wi = new WithInner();而不是.super()?
这不会将创建的WithInner
实例与内部类实例相关联。您得到编译时错误,因为您的InheritInner
构造函数不再显式调用合成超类构造函数,并且无法隐式调用它,因为它需要外部实例关联的参考。将外部实例引用视为内部类构造函数的隐藏参数(实际上,它是如何在引擎盖下实现的)可能是最容易的。
在调用wi.super()时我们调用的是Object的默认构造函数,不是吗?
不,您正在调用WithInner.Inner
构造函数,该构造函数具有"隐藏"外部实例引用的参数; wi
基本上作为隐藏参数值传递给WithInner.Inner
构造函数。