2

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

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

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();
    }
}

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

我希望输出为“2”。但相反,我有一个编译错误System.out.println(A.this.i);

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

我认为我试图解决的编程概念是合理的:在内部创建一种新类型的 Bmain以提供给 A,它使用 B 类型可以访问的 A 中的东西。

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

编辑/更新:请注意,将代码main移至非静态方法时会出现相同的错误。也就是说,我尝试将其中的所有内容移动static void main到一个新的、非静态方法被class Main调用go()。然后我改为static void main单行new Main().go();。错误在同一个地方。所以这似乎不是class C在静态上下文中定义的问题。

4

3 回答 3

3

这是您永远不应该为生产编写的荒谬代码。

它部分地在Explicit Constructor Invocations的文档中进行了解释

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

所有这一切都说这C是一个本地类(这是一个inner类,这是一种废话,因为如果你在一个static方法中声明它没有封闭的实例),它是一个子类,B但不是一个嵌套类A。因此,没有封闭的实例。的实例C没有封闭实例。(虽然如果你在实例方法中声明它会这样,但这将是一个实例Main。)

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

你必须自己存储它

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

既然A#ipublic,你可以正常访问它

public void show() {
    System.out.println(enclosingInstance.i);
}
于 2015-10-09T01:19:20.667 回答
3

您想A.this引用实例的封闭B实例。但为什么要这样做?这不是语法的意思。A.this将意味着实例的封闭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();
    }
}

这里Cextends B, 和C都是B的内部类A。因此 anyC有一个封闭的实例,当被认为是 a 时A它也有一个封闭的实例,并且这些封闭的实例是不同的(事实证明和打印不同的数字)。ABfoobar

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

于 2015-10-09T01:38:03.423 回答
1

使用提供的信息,我会这样做:

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

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

于 2015-10-09T01:07:25.520 回答