方法本地内部类与内部类

Ram*_*tra 44 java inner-classes

以下代码生成输出middle.谁能详细解释这是怎么回事?

是因为声明"内部"版本class A来自在方法中class A创建的实例之后go()

class A {
    void m() {
        System.out.println("outer");
    }
}

public class MethodLocalVSInner {
    public static void main(String[] args) {
        new MethodLocalVSInner().go();
    }

    void go() {
        new A().m();
        class A {
            void m() {
                System.out.println("inner");
            }
        }
    }

    class A {
        void m() {
            System.out.println("middle");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Roh*_*ain 38

我猜你期望调用本地类方法.这没有发生,因为你在new A()本地范围之外使用.因此,它访问范围中的下一个更接近的候选者,即内部类.来自JLS§6.3:

由块(第14.2节)直接包含的本地类声明的范围是直接封闭块的其余部分,包括它自己的类声明.

因此,new A()在第一行方法中,将不会访问出现在它之后的本地类.如果在此之前移动类声明,您将获得预期的输出.

另请参阅JLS§14.3,其中包含类似示例.

  • @KisHanSarsecHaGajjar你为什么写这么多惊叹号? (4认同)
  • @Ramswaroop你的问题的答案可能只是Java架构师选择本地类来表现这种方式. (2认同)

Tim*_*sen 17

由于您拥有代码的顺序,您将获得输出"中间".由于方法范围class A发生您的调用之后new A(),您将获得输出"中间".如果您按如下方式切换订单,您将获得输出"内部":

void go() {
    class A {
        void m() {
            System.out.println("inner");
        }
    }
    new A().m();
}
Run Code Online (Sandbox Code Playgroud)

输出:

inner

实例化的优先顺序,class A从高到低,是:

  1. 方法

有关更多信息,请查看讨论内部类的官方Java语言规范.

  • 这也是OP也猜到的.但那是为什么呢?请备份你的答案. (3认同)

Rad*_*def 7

inner没有打印的原因是(6.3):

由块直接包含的本地类声明的范围是直接封闭块的其余部分,包括它自己的类声明.

(在方法内声明的类称为本地类.)

所以A不能引用本地类,因为表达式new A()在声明之前发生.换句话说,本地类与局部变量具有相似的范围.

middle打印原因而不是outer内部类A 隐藏顶级类A(6.4.1):

一个声明d命名类型的n阴影任何其他类型的命名的声明n是在[...]范围d.

这意味着在身体的任何地方MethodLocalVSInner,不合格的人A必须引用内部阶级.

如果您熟悉成员变量的阴影,例如:

class Example {
    int x;
    void setX(int x) {
        //       ? 'x' refers to the local method parameter
        this.x = x;
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上同样的事情是继续进行类声明.