Java内部类的层次结构

发布于 2024-11-19 11:48:58 字数 508 浏览 2 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

婴鹅 2024-11-26 11:48:58

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

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

尝试这样,

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

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

    public static void main(String args[])  {

    }      
}

类似的问题: 奇怪“在调用超类型构造函数之前无法引用 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,

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

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

    public static void main(String args[])  {

    }      
}

Similar question : Odd situation for “cannot reference this before supertype constructor has been called”

烈酒灼喉 2024-11-26 11:48:58

另一位海报是正确的,但如何解决?只需将您的类设置为静态:

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

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

The other poster is correct, but how to fix? Simply make your class static:

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

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).

豆芽 2024-11-26 11:48:58

您的代码在 Java 7 下编译。

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

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

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

然而,语言规范似乎并不能保证这一点。参见#8.1.3。由于 B 不是C立即词法包含的,因此 B 不是 C 的直接内部类,没有理由说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)

Your code compiles under Java 7.

The following workaround compiles under Java 6.

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

@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 that C.this is the enclosing instance for B's super(), therefore C(){super();} is actually C(){C.this.super();}. Since C.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 by C, B is not a direct inner class of C, there is no reason to say that B's direct enclosing instance must be an instance of C.

We need to pass B() an instance of A. It is true that C.this is an instance of A ( 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 to C()).

According to javap, javac 7 compiles the code into

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文