public class Outer {
class Inner1 extends Outer{
public Inner1() {
super(); // 调用 Object() 构造器
}
}
class Inner2 extends Inner1{
public Inner2() {
super(); // 调用 Inner1() 构造器 No enclosing instance of type Outer is available due to some intermediate
//constructor invocation
}
}
class Inner3 extends Inner2{
public Inner3(){
super(); //No enclosing instance of type Outer is available due to some intermediate
//constructor invocation
}
}
}
</pre><pre name="code" class="java">
<span style="font-family: TT1F18o00; font-size: 12pt;"></span><pre name="code" class="java">当超类是非静态内部类时,调用超类的构造器,会显示No enclosing instance of type Outer is available due to some intermediate constructor invocation编译错误。
因为
Inner2 的超类本身也是一个内部类,一个晦涩的语言规则登场了 。正如大家知道的,要想实例化一个内部类,如类 Inner1,需要提供一个外部类的实例给构造器。一般情况下,它是隐式地传递给构造器的,但是它也可以以expression.super(args)的方式通过超类构造器调用(superclass constructorinvovation)显式地传递[JLS 8.8.7] 。如果外部类实例是隐式传递的,编译器会
自动产生表达式:它使用 this 来指代最内部的其超类是一个成员变量的外部类。这确实有点绕口,但是这就是编译器所作的事情。在本例中,那个超类就是
Inner1。因为当前类 Inner2 间接扩展了 Outer 类,Inner1便是它的一个继承而来的成员。因此, 超类构造器的限定表达式直接就是 this。编译器提供外部类
实例,将 super重写成 this.super。解释到这里,编译错误所含的意思可扩展为:
Outer. java:12:cannot reference this before
supertype constructorhas been called
this.super();
^
现在问题就清楚了 :缺省的Inner2 的构造器试图在超类构造器被调用前访问this,这是一个非法的操作[JLS 8. 8. 7.1]。 解决这个问题的蛮力方法是显式地传递合理的外部类实例:
public class Outer {
class Inner1 extends Outer {}
class Inner2 extendsInner1{
public Inner2() {
Outer.this.super();
}
}
}这样可以通过编译,但是它太复杂了 。这里有一个更好的解决方案:无论何时你
写了一个成员类,都要问问你自己,是否这个