Java内部类的层次结构
我正在使用内部类的层次结构来表示应用程序中的一些数据,但我遇到了一条我根本不理解的错误消息。我的代码可以归结为以下最小示例:
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 已经生成了与内部类相关的东西。
我找到了另一种方式来表示我的数据,所以我只是对为什么它不能编译的一个很好的解释感兴趣。
I am using a hierarchy of inner classes to represent some data in an application and I have run into an error message that I simply do not understand. My code can be boiled down to the following minimal example:
public class A {
public class B extends A {}
public class C extends B {}
}
Javac (and my IDE of course) fails to compile the code with the following error message:
A.java:3: cannot reference this before supertype constructor has been called
public class C extends B {}
^
1 error
I didn't write this
anywhere. There is no more code than provided above, so I assume javac has generated something related to the inner class.
I have found another way to represent my data, so I am simply interested in a good explanation of why it doesn't compile.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要一个外部类实例来创建内部类实例,即类似于
new Outer().new Inner();
用另一个内部类(子内部类)扩展内部类(父内部类) ),你不能调用“父内部类”的构造函数,因为“外部类”的实例不存在。
尝试这样,
类似的问题: 奇怪“在调用超类型构造函数之前无法引用 this”的情况
You need an outer class instance to create an inner class instance i.e something like
new Outer().new Inner();
To extend the inner class (Parent inner class) with another inner class (child inner class), you cannot call the constructor of 'parent inner class' because the instance of 'outer class' is not there.
Try like this,
Similar question : Odd situation for “cannot reference this before supertype constructor has been called”
另一位海报是正确的,但如何解决?只需将您的类设置为静态:
请注意,如果您的内部类引用外部类的字段,则不能将它们设置为静态,否则可以(并且应该 - 这样做可以减少依赖性)。
The other poster is correct, but how to fix? Simply make your class
static
:Note that if your inner classes refer to fields of the outer class, you can't make them static, otherwise you can (and should - doing so reduces dependencies).
您的代码在 Java 7 下编译。
以下解决方法在 Java 6 下编译。
@saugok 指向上一个问题的链接引用了 Joshua 的解释。基本上他认为,由于 C 是 A 的子类,因此 C 继承 A 的成员作为 C 的成员。因此B也是C的成员。 (例如,类文字
CBclass
是有效的。)因此,他认为C.this
是B 的 super()
的封闭实例,因此C(){super();}
实际上是C(){C.this.super();}
。由于C.this
无法在超级构造函数之前求值,因此会出现错误。然而,语言规范似乎并不能保证这一点。参见#8.1.3。由于
B
不是C
立即词法包含的,因此B
不是C 的直接内部类
,没有理由说B
的直接封闭实例一定是C
的实例。我们需要传递
B()
一个A
的实例。确实,C.this
是A
的一个实例(尝试以下代码:new C().new B().new C().new B();
) 因此它可能是一个候选者。还有另一个候选者,A.this
。A.this
可用并可以使用(它作为隐藏参数传递给C()
)。根据
javap
,javac 7将代码编译为Your code compiles under Java 7.
The following workaround compiles under Java 6.
@saugok's link to the previous question quoted Joshua's explanation. Basically he argued that since C is subclass of A, C inherits A's members as C's members. Therefore B is also C's member. (For example a class literal
C.B.class
is valid.) Therefore he argues thatC.this
is the enclosing instance forB's super()
, thereforeC(){super();}
is actuallyC(){C.this.super();}
. SinceC.this
cannot be evaluated before super constructor, thus the error.However this doesn't seem to be warranted by the language spec. See #8.1.3. Since
B
is not immediately lexically enclosed byC
,B
is not a direct inner class ofC
, there is no reason to say thatB
's direct enclosing instance must be an instance ofC
.We need to pass
B()
an instance ofA
. It is true thatC.this
is an instance ofA
( try this code:new C().new B().new C().new B();
) therefore it could be a candidate. There is also another candidate,A.this
.A.this
is available and ready to use (it's passed in as the hidden parameter toC()
).According to
javap
, javac 7 compiles the code into