当前位置: 首页 > 知识库问答 >
问题:

为什么扩展内部类的局部类不能访问封闭实例的内部类?

公孙阳羽
2023-03-14

(我一直在重读那个问题标题,思考它看起来有多荒谬,但我向你保证,这是对问题的最佳描述,我有一个实际的应用程序,其中这是最好的结构。我发誓我没有疯。)

考虑以下内容。每个块都是一个单独的文件:

package myPackage;

public class A {

    public int i;

    public A(int i) {
        this.i = i;
    }

    public class B {

    }
}
package myPackage;

import myPackage.A.B;

public class Main {

    public static void main(String[] args) {
        class C extends B {
            public C(A enclosingInstance) {
                enclosingInstance.super();
            }

            public void show() {
                System.out.println(A.this.i);
            }
        }
        A myA = new A(2);
        C myC = new C(myA);
        myC.show();
    }
}

注意,enclosinstance业务是为了解决涉及中间构造函数调用的问题。请参阅“为什么外部类不能扩展内部类?”。

我希望输出为“2”。但是相反,我在System.out.println(a.this.I)上有一个编译错误

范围内无法访问类型A的封闭实例

我认为我试图解决的编程概念是合理的:在main中创建一个新类型的B,给a一个使用a中B可以访问的东西的类型。

那么我做错了什么,或者为什么这在java中不可能呢?

编辑/更新:请注意,将主中的代码移到非静态方法时,会出现相同的错误。也就是说,我尝试将静态void main中的所有内容移动到一个新的非静态方法,名为go()。然后我将静态void main改为单行 。误差在同一点上。因此,在静态上下文中定义C类似乎不是一个问题。

共有3个答案

井轶
2023-03-14

根据提供的信息,我会这样做:

public class B {
    protected A getOuterInstance() {
        return A.this;
    }
}

并且让C继承并使用此方法。我知道您不喜欢这种方法,但这是我能看到的最简单的答案。有了更多信息,我可能会提出一个尽量不涉及任何内部类的设计,因为这不是内部类的正常用例。

濮阳君浩
2023-03-14

这是一段荒谬的代码,你永远不应该为产品而写。

显式构造函数调用的留档部分解释了这一点

合格的超类构造函数调用以表达式或ExpressionName开头。它们允许子类构造函数显式指定新创建对象的直接封闭实例相对于直接超类(§8.1.3)。当超类是内部类时,这可能是必要的。

所有这一切都表明,C是一个局部类(这是一个内部类,这是一种无稽之谈,因为如果在静态方法中声明它,就没有封闭实例),它是B的子类,但不是a的嵌套类。因此,不存在封闭实例。C的实例没有封闭实例。(虽然如果您在实例方法中声明它,它会出现,但那将是Main的实例)

新创建的对象的立即封闭实例(来自JLS)是通过构造函数参数间接指定的。

你必须自己储存

private A enclosingInstance;
public C(A enclosingInstance) throws CloneNotSupportedException {
    enclosingInstance.super();
    this.enclosingInstance = enclosingInstance;
}

由于A#i是公共的,所以您可以正常访问它

public void show() {
    System.out.println(enclosingInstance.i);
}
钱钊
2023-03-14

你想要一个。这是指B实例的封闭实例。但为什么要这样呢?这不是语法的意思<代码>A。这意味着C实例的封闭实例,这没有意义,因为C不是A的内部类。

为了更清楚地说明这一点,这里有一个示例,其中C是A的内部类。

public class A {

    public int i;

    public A(int i) {
        this.i = i;
    }

    public class B {
        void foo() {
            System.out.println(A.this.i);
        }
    }

    public class C extends B {
        C(A a) {
            a.super();
        }
        void bar() {
            System.out.println(A.this.i);
        }
    }

    public static void main(String[] args) {
        A a1 = new A(1);
        A a2 = new A(2);
        C c = a1.new C(a2);
        c.foo();
        c.bar();
    }
}

这里,C扩展了B,C和B都是A的内部类。因此,任何C都有一个封闭的A实例,当被视为B实例时,它也有一个封闭的A实例,这些封闭实例是不同的(事实证明,foo和bar打印不同的数字)。

所以,A。这个不可能意味着你想要它意味着什么,因为它已经意味着其他东西。我想语言设计者之所以没有想出其他语法来表示一个超类的封闭实例,是因为这种语法非常复杂,几乎没有回报(简单的解决方法已经存在)。

 类似资料:
  • 为什么我不能这样做/是否有解决方法来实现这一点: 这两个编译错误是 > On

  • 我认为内部类的成员,即使被声明为私有的,也可以从它的封闭类中访问。但是我遇到了以下代码结构的编译时错误。我的顶级类实现了Iterable接口。Iterator在内部类中实现。当内部类的一个实例通过iterator()方法获得时,我无法使用该实例访问数据栏。 有什么建议吗?

  • 我知道如果我想扩展内部类,我应该这样做: 但是在这种情况下,我不明白该怎么办?如何获取内部对象的封闭实例? 此变体不编译:

  • 问题内容: 在下面显示的代码片段中,内部类本身继承了外部类。 方法中的唯一语句(最后一个片段)将值分配给类的私有字段,然后调用该方法。 该方法会导致另一个字符串- 要设置的私人领域中的类调用之前的方法延长。 因此,方法中的以下两个语句: 应该显示 另一个价值 另一个价值 但是他们显示 初始值 初始值 为什么会这样? 问题答案: 方法和领域都是。因此,其他子类(包括子类)均无法访问它们。它们不是继承

  • 在阅读java Doc时,我得到了以下东西。 内部类C是类O的直接内部类,如果O是C的直接词汇封闭类,并且C的声明不发生在静态上下文中 所以如果我写信 我的问题是在这两个内部类中,哪一个是O的直接内部类? 我也有一些观点。 2.如果类O是C的第n-1个词汇封闭类的直接封闭类,则它是C的第n个词汇封闭类。 3.类O的直接内部类C的实例i与O的实例关联,称为i的直接封闭实例。对象的直接封闭实例(如果有