java 内部类 方法_java-方法本地内部类与内部类

java-方法本地内部类与内部类

下面的代码产生输出class A。谁能详细解释这是怎么发生的?

是否因为在go()方法中创建class A的实例之后才出现29737083357170170768的“内部”版本声明?

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");

}

}

}

6个解决方案

38 votes

我猜您期望本地类方法被调用。 那没有发生,因为您正在使用new A()超出本地类的范围。 因此,它访问范围内的下一个更接近的候选对象,即内部类。 根据JLS§6.3:

紧接在块中的局部类声明的范围(第14.2节)是紧随其后的块的其余部分,包括它自己的类声明。

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

另请参见JLS§14.3,其中包含类似的示例。

Rohit Jain answered 2020-07-19T18:49:26Z

17 votes

由于代码的顺序,您将获得“中间”输出。 由于在调用class A之后发生了方法范围为297370921642020142014的情况,因此您将获得输出“ middle”。 如果按以下方式切换顺序,则将获得输出“ inner”:

void go() {

class A {

void m() {

System.out.println("inner");

}

}

new A().m();

}

输出:

class A

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

方法

请查看有关内部类的正式Java语言规范,以获取更多信息。

Tim Biegeleisen answered 2020-07-19T18:50:17Z

7 votes

无法打印MethodLocalVSInner的原因是(6.3):

一个块紧紧包围的局部类声明的范围是紧紧包围的块的其余部分,包括它自己的类声明。

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

因此MethodLocalVSInner无法引用本地类,因为表达式A出现在声明之前。 换句话说,局部类的作用域与局部变量相似。

打印MethodLocalVSInner而不是A的原因是内部类n遮盖了顶级类d(6.4.1):

类型为A的声明MethodLocalVSInner遮盖了范围为d的任何其他类型的名为n的声明。

这意味着在MethodLocalVSInner正文中的任何位置,不合格的A必须引用内部类。

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

class Example {

int x;

void setX(int x) {

// ┌ 'x' refers to the local method parameter

this.x = x;

}

}

本质上,类声明也是如此。

Radiodef answered 2020-07-19T18:51:13Z

4 votes

情况1:

void go() {

new A().m();

class A {

void m() {

System.out.println("inner");

}

}

}

在这种情况下,如果您在本地类范围之外运行方法。 那就是为什么它将打印middle

情况2:

void go() {

class A {

void m() {

System.out.println("inner");

}

}

new A().m();

}

在这种情况下,它将打印inner,因为该类现在在范围内。

Sumit Singh answered 2020-07-19T18:51:46Z

2 votes

在方法中:

void go() {

new A().m();

class A {

void m() {

System.out.println("inner");

}

}

}

当方法开始执行时,将执行第一行inner

并且因为内部类已经在范围内,所以将创建该类的对象,并且将为inner class而不是为local method class调用inner方法,因为它仍不在范围内。 这就是为什么您得到middle作为输出的原因。

但是如果您将方法更改为:

void go() {

class A {

void m() {

System.out.println("inner");

}

}

new A().m();

}

您的本地方法类现在将在范围内,并且具有更高的优先级,因此您现在将获得输出inner。

Prashant answered 2020-07-19T18:52:23Z

1 votes

您正在使用A class的实例调用A()方法

里面的方法您正在创建A()的实例在这里,因为您没有显式导入外部A class,并且直接内部类位于方法调用语句之后,所以JVM选择了MethodLocalVSInner的类级别的inner class A,并在其中执行go方法

Thusitha Thilina Dayaratne answered 2020-07-19T18:52:48Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值