外部class调用内部class的方法

Way to call inner class by outer class

我知道要实例化一个内部成员class,你有两个不同的构造函数:

第一个:

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

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

将调用第一个主要方法

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

从这里您创建了一个 Outer class 的对象并调用了如下所示的 callInner 方法

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

现在您已经创建了一个 Inner 对象并调用了 go 方法。

 protected class Inner {
        public int repeat=3;

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

所以这是一个简单的调用,所有调用都在同一范围内。所以需要 outer.Inner 概念来调用。

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

如您的解释所示,您需要 Outer 的实例来创建 Inner 的实例。由于方法 callInnerOuter 的实例方法(未声明 [​​=17=]),因此已经存在 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,其中 loads in instance methods this


比较:Java Tutorials - Inner Class Example

当你调用callInner方法时,你实际上是在Outerclass的范围内。为什么编译器接受调用 new Inner() 是完全相同的,为什么你不必明确地写出 class 你想象中的静态变量来自什么(当它是同一个 class 你叫它)。请参见下面的示例:

public class Outer {
  private static int x = 1;

  private void innerCall() {
    x++;
  }
}

在上面的例子中,你做的和你的例子完全一样,除了例外,你使用 class 而不是变量(这在这里并不真正相关)。如果想从 class(作用域)外部访问 class/variable,您的语法是必需的。然后它看起来像下面的东西:

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

Outer.x++;

在上面,您必须明确指定要从哪个范围访问变量 x。就像您想从给定目录中访问文件一样。如果您在此目录中,则只需通过文件名访问该文件。但是,当你在它外面时,你还必须写下目录的名称才能看到你想要获取的文件。