我使用内部类的层次结构来表示应用程序中的一些数据,并且我遇到了一条我根本不理解的错误消息。我的代码可以归结为以下最小的例子:
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已经生成了与内部类相关的东西。
我找到了另一种表示我的数据的方法,所以我只是对它为什么不编译的一个很好的解释感兴趣。
答案 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.this
是B's super()
的封闭实例,因此C(){super();}
实际上是C(){C.this.super();}
。由于C.this
在超级构造函数之前无法求值,因此错误。
然而,语言规范似乎并不保证这一点。见#8.1.3。由于B
不是C
B
,C
不是<{1}}的直接内部类,因此没有理由说B
的直接封闭实例必须是C
的实例。
我们需要传递B()
A
的实例。确实C.this
是A
的实例(尝试此代码:new C().new B().new C().new B();
)因此它可能是候选者。还有另一位候选人A.this
。 A.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)