Java中内部类的层次结构

时间:2011-07-12 07:52:59

标签: java inheritance constructor inner-classes

我使用内部类的层次结构来表示应用程序中的一些数据,并且我遇到了一条我根本不理解的错误消息。我的代码可以归结为以下最小的例子:

public class A {
    public class B extends A {}
    public class C extends B {}
}

Javac(当然我的IDE)无法使用以下错误消息编译代码:

A.java:3: cannot reference this before supertype constructor has been called
    public class C extends B {}
           ^
1 error

我没有在任何地方写this。没有比上面提供的更多的代码,所以我假设javac已经生成了与内部类相关的东西。

我找到了另一种表示我的数据的方法,所以我只是对它为什么不编译的一个很好的解释感兴趣。

3 个答案:

答案 0 :(得分:8)

您需要一个外部类实例来创建内部类实例,例如new Outer().new Inner();

要使用另一个内部类(子内部类)扩展内部类(Parent内部类),不能调用“父内部类”的构造函数,因为“外部类”的实例不存在。

试试这个,

public class A{        
    public class B extends A {
        B() { }  
    }    

    public class C extends B {
        C() { 
            new A().super();  
        }  
    }    

    public static void main(String args[])  {

    }      
}

类似的问题:Odd situation for “cannot reference this before supertype constructor has been called”

答案 1 :(得分:2)

另一张海报是正确的,但如何解决?只需制作课程static

public class A {
    public static class B extends A {}
    public static class C extends B {}
}

请注意,如果您的内部类引用外部类的字段,则不能将它们设置为静态,否则您可以(并且应该这样做会减少依赖性)。

答案 2 :(得分:1)

您的代码在Java 7下编译。

以下解决方法在Java 6下编译。

    public class C extends B
    {
        public C()
        {
            A.this.super();
        }
    }

@saugok与前一个问题的链接引用了约书亚的解释。基本上他认为,由于C是A的子类,C继承A的成员作为C的成员。因此B也是C的成员。 (例如,类文字C.B.class有效。)因此,他认为C.thisB's super()的封闭实例,因此C(){super();}实际上是C(){C.this.super();}。由于C.this在超级构造函数之前无法求值,因此错误。

然而,语言规范似乎并不保证这一点。见#8.1.3。由于B不是C BC不是<{1}}的直接内部类,因此没有理由说B的直接封闭实例必须是C的实例。

我们需要传递B() A的实例。确实C.thisA的实例(尝试此代码:new C().new B().new C().new B();)因此它可能是候选者。还有另一位候选人A.thisA.this可用且可以使用(它作为隐藏参数传递给C())。

根据javap,javac 7将代码编译成

class B
    private A this$0;
    B( A a )
        this$0 = a;
        super(); // A()

class C extends B
    private A this$0;
    C( A a )
        this$0 = a;
        super( a ); // B(A)