通过外部类调用内部类的方法



我知道要实例化成员内部类,需要两个不同的构造函数:

第一:

Outer out = new Outer();
Outer.Inner in = out.new Inner();

第二:

Outer.Inner in = new Outer().new Inner();

现在,我不知道为什么这个代码会编译:

public class Outer {
private String greeting="Hi";
protected class Inner {
public int repeat=3;
public void go() {
for (int i =0; i<repeat; i++) {
System.out.println(greeting);
}
}
}
public void callInner() {
Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
in.go();
}
public static void main(String[] args) {
Outer out = new Outer();
out.callInner();
}
}

为什么要编译?

非常感谢!

当您在Outer的范围内(在实例方法内(实例化Inner时,您不需要显式实例化引用Outer类,就像您的示例中一样:

Outer.Inner in = new Outer().new Inner();

只引用Inner:实例化是可以的

Inner in = new Inner();

这适用于类中的所有实例方法,只要它们不是静态的。

第一个主方法将被称为

public static void main(String[] args){
Outer out = new Outer();
out.callInner();
}

从这里开始,您创建了一个Outer类的对象,并称之为callInner方法,如下所示

public void callInner() {
Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
in.go();
}

现在您已经创建了一个名为"内部"的对象,并称之为go方法。

protected class Inner {
public int repeat=3;
public void go() {
for (int i =0; i<repeat; i++) {
System.out.println(greeting);
}
}
}

所以这是一个简单的调用,所有调用都在同一范围内。因此需要外部。内部概念调用。

重要的是要理解外在和内在是相关的。更具体地说,您需要一个外部实例才能创建内部实例。

正如您的解释所示,您需要一个Outer的实例来创建Inner的实例。由于方法callInnerOuter的实例方法(未声明为static(,因此已经存在Outer的实例:this

代码也可以这样写:

public void callInner() {
Outer out = this;
Inner in = out.new Inner();
in.go();
}

现在,代码看起来与您的第一个示例相似。

但让我们保持代码如图所示:

public void callInner() {
Inner in = new Inner();
in.go();
}

现在,如果我们从引擎盖下看,它基本上是一样的:

public void callInner();
Code:
0: new           #21                 // class playground/Outer$Inner
3: dup
4: aload_0
5: invokespecial #23                 // Method playground/Outer$Inner."<init>":(Lplayground/Outer;)V
8: astore_1
9: aload_1
10: invokevirtual #26                 // Method playground/Outer$Inner.go:()V
13: return

在第4行,我们得到了aload_0,它加载了实例方法this


比较:Java教程-内部类示例

当您调用callInner方法时,您实际上在Outer类的范围内。编译器接受调用new Inner()的原因是完全一样的,为什么你不必明确地写你想象中的静态变量来自哪个类(当它是你调用它的同一类的一部分时(。参见以下示例:

public class Outer {
private static int x = 1;
private void innerCall() {
x++;
}
}

在上面的情况下,除了使用类而不是变量(这在这里并不真正相关(之外,您所做的与示例中完全相同。如果希望从类(作用域(外部访问类/变量,则需要使用语法。然后它看起来像下面的东西:

public class Outer {
public static int x = 1;
}
Outer.x++;

上面,您必须明确指定要从哪个范围访问变量x。这就像您想要从给定目录中访问文件一样。如果你在这个目录中,你只需要按文件名访问它。然而,当你在它之外时,你还必须写下目录的名称,才能看到你想要得到的文件。

最新更新